4

前の例を再利用して、新しく到着した動物を飼育係が「処理」する必要がある動物園を想像してみてください(動物園にチェックインすることを考えてください)。各動物のチェックインプロセスは、クラスの分類(哺乳類、鳥など)によって異なります。

分類法のクラス間の基本的な違いのために、プロセスは異なります。たとえば、鳥には翼があり、哺乳類には歯があります。また、すべての動物に当てはまるプロセスの共有ビットがあるかもしれませんが、ここではそれらを省略しました。

コードは次のとおりです。

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コアを変更せずにを追加できるようにすることです。

4

2 に答える 2

5
public interface Animal<THIS extends Animal<THIS>> {
    AnimalProcessor<THIS> getAnimalProcessor();
}
public abstract class Mammal implements Animal<Mammal> {

少し似てEnum<E extends Enum<E>>います。

メソッドを削除することをお勧めします。

于 2012-06-27T14:44:44.997 に答える
2

AnimalProcessor.java:

public interface AnimalProcessor<T extends Animal> {
    public void process(Animal critter);
}

MammalProcessor.java

public class MammalProcessor implements AnimalProcessor<Mammal> {
    @Override
    public void process(Animal a) {
        System.out.println("Tooth count is " + ((Mammal)a).getToothCount());
    }
}
于 2012-06-27T15:52:32.217 に答える