Why doesn't the following compile:
CODE 1
public class Main {
static abstract class Animal {
abstract String sound();
}
static class Dog extends Animal {
@Override
String sound() {
return "bark";
}
}
static abstract class Printer<T> {
public abstract void callPrint(T t);
}
static abstract class AnimalPrinter<T extends Animal> extends Printer<T>
{
@Override
public void callPrint(T t) {
System.out.println("AnimalPrinter calling print: " + t.sound());
}
}
static class DogPrinter extends AnimalPrinter<Dog> {
@Override
public void callPrint(Dog d) {
System.out.println("DogPrinter calling print: " + d.sound());
}
}
public static void main(String[] args) {
// I'M OK WHICH I UNDERSTAND
AnimalPrinter<Dog> someDogPrinterOK = new DogPrinter();
Printer<Animal> animalPrinterOK = new AnimalPrinter<Animal>(){};
// WHY IS THE FOLLOWING NOT ALLOWED
AnimalPrinter<Animal> someDogPrinterNOTOK = new DogPrinter();
Printer<Animal> dogPrinterNOTOK = new DogPrinter();
}
}
I do not understand why the last two lines do not compile. Why isn't DogPrinter a subtype of AnimalPrinter or Printer. Very sad I cannot do this as I was refactoring code to have better type parameters. This question may be a duplicate but I just am unable to find it on SO, kind of hard to search for. My software-religious belief is that the last two lines should compile as they conform to the super-types interface. If the above is not allowed why is the following ok:
CODE 2
public class Main2
{
static abstract class Animal {
abstract String sound();
}
static class Dog extends Animal {
@Override
String sound() {
return "bark";
}
}
static abstract class AnimalGetter {
private Animal animal;
AnimalGetter(Animal animal) {
this.animal = animal;
}
Animal getAnimal(){
return animal;
}
}
static class DogGetter extends AnimalGetter{
Dog dog;
DogGetter(Dog dog) {
super(dog);
this.dog = dog;
}
Dog getAnimal(){
return dog;
}
}
}
I would have thought if CODE1, doesn't work then neither would CODE2. This makes no sense to me.