0

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.

Derrops
  • 7,651
  • 5
  • 30
  • 60

0 Answers0