前の例を再利用して、新しく到着した動物を飼育係が「処理」する必要がある動物園を想像してみてください(動物園にチェックインすることを考えてください)。各動物のチェックインプロセスは、クラスの分類(哺乳類、鳥など)によって異なります。
分類法のクラス間の基本的な違いのために、プロセスは異なります。たとえば、鳥には翼があり、哺乳類には歯があります。また、すべての動物に当てはまるプロセスの共有ビットがあるかもしれませんが、ここではそれらを省略しました。
コードは次のとおりです。
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(critter)はコンパイルできません。これはタイプでAnimalProcessor<Bird>
はないAnimalProcessor<Animal>
ためですが、問題を解決する方法がわかりません。を呼び出すと<T extends Animal>
getAnimalProcessor()
適切なが返されますAnimalProcessor<T extends Animal>
が、これをコードで表現することはできません。
おそらく、そもそもAnimalProcessorを引き出すべきではないのでしょうか。
もちろん、目標はReptile
コアを変更せずにを追加できるようにすることです。