Повторяя предыдущий пример, представьте себе зоопарк, в котором новоприбывшие животные должны быть «обработаны» Zookeeper (подумайте о том, чтобы проверить их в зоопарке). Процесс регистрации каждого животного зависит от его таксономии класса (млекопитающее, птица и т. Д.).Какое правильное использование генериков разрешает эту ошибку компиляции?
Процессы отличаются из-за фундаментальных различий между классами таксономии - например, у птиц есть крылья, у млекопитающих есть зубы. У вас также могут быть некоторые общие бит процесса, которые верны для всех животных, но я опустил их здесь.
Вот код:
Animal.java
public interface Animal {
public AnimalProcessor<? extends Animal> getAnimalProcessor();
}
Mammal.java
public abstract class Mammal implements Animal {
@Override
public AnimalProcessor<Mammal> getAnimalProcessor() {
return new MammalProcessor();
}
// Specific to mammals
public abstract int getToothCount();
}
Bird.java
public abstract class Bird implements Animal {
@Override
public AnimalProcessor<Bird> getAnimalProcessor() {
return new BirdProcessor();
}
// Specific to birds
public abstract float getWingspan();
}
AnimalProcessor.java
public interface AnimalProcessor<T extends Animal> {
public void process(T critter);
}
MammalProcessor.java
public class MammalProcessor implements AnimalProcessor<Mammal> {
@Override
public void process(Mammal a) {
System.out.println("Tooth count is " + a.getToothCount());
}
}
BirdProcessor.java
public class BirdProcessor implements AnimalProcessor<Bird> {
@Override
public void process(Bird a) {
System.out.print("Wingspan is " + a.getWingspan());
}
}
Badger.java
public class Badger extends Mammal {
@Override
public int getToothCount() {
return 40;
}
}
Condor.java
public class Condor extends Bird {
@Override
public float getWingspan() {
return 2.9f;
}
}
ZooKeeper.java
import java.util.List;
public class ZooKeeper {
public void processNewAnimals(List<Animal> newcomers)
{
for(Animal critter : newcomers)
{
AnimalProcessor<? extends Animal> ap = critter.getAnimalProcessor();
// This line has a compilation error!
ap.process(critter);
}
}
}
MainClass.java
import java.util.LinkedList;
import java.util.List;
public class MainClass {
public static void main(String[] args) {
ZooKeeper keeper = new ZooKeeper();
List<Animal> animals = new LinkedList<Animal>();
animals.add(new Badger());
animals.add(new Condor());
keeper.processNewAnimals(animals);
}
}
Там нет никаких предупреждений в любом месте, но ap.process (зверушка) не может скомпилировать. Я знаю, это потому, что AnimalProcessor<Bird>
не типа AnimalProcessor<Animal>
, но я не вижу, как решить проблему. Вызов <T extends Animal>
getAnimalProcessor()
вернет подходящий AnimalProcessor<T extends Animal>
, но я не могу выразить это в коде.
Возможно, я не должен вытаскивать AnimalProcessor в первую очередь?
Цель состоит в том, чтобы, конечно, добавить Reptile
, не меняя ядро.
Почему животное интерфейс вместо абстрактный класс? Интерфейс должен быть своего рода совместным поведением. – carmenism
Я принимаю ваше решение, и я изменил его в своем коде, но ошибка компиляции остается. – pjm56