例如,我得到了3个类:
超类:Animal
子类扩展超类:Cat
,Tiger
。
我编写了一个检查器类AnimalChecker
来区分动物的类型,并使每个类型调用不同的方法(不同类型的参数,相同的方法名称)。如果使用C++模板,就有可能完成这类工作,想知道他们用Java使其工作的简单方法是什么,我做了一些尝试,但还没有得到。:
AnimalChecker
定义如下:
public abstract class AnimalChecker {
private List<Class<? extends Animal>> mAnimals;
public AnimalChecker(Class<? extends Animal>... animals) {
mAnimals = Arrays.asList(animals);
}
public boolean CheckAnimal(Animal animal) {
Iterator<Class<? extends Animal>> it = mAnimals.iterator();
while (it.hasNext()) {
Class clazz = it.next();
if (clazz.isInstance(animal)) {
onCheck(animal, clazz);
return true;
}
}
return false;
}
public abstract void onCheck(Animal animal, Class<? extends Animal> clazz);
}
然后我尝试实现这个类,为每种类型做具体的工作:
public class Main {
public static MyChecker msChecker = new MyChecker();
public static void main(String[] args) {
AnimalChecker checker = new AnimalChecker(Cat.class, Tiger.class) {
@Override
public void onCheck(Animal animal, Class<? extends Animal> clazz) {
System.out.println(clazz.toGenericString());
msChecker.onCheck(clazz.cast(animal));
}
};
checker.CheckAnimal(new Tiger());
checker.CheckAnimal(new Cat());
MyChecker myChecker = new MyChecker();
myChecker.onCheck(new Tiger());
myChecker.onCheck(new Cat());
}
static class MyChecker {
public void onCheck(Animal animal) {
System.out.println("Animal");
}
public void onCheck(Cat animal) {
System.out.println("Cat");
}
public void onCheck(Tiger animal) {
System.out.println("Tiger");
}
}
}
下面的输出不是我想要的:
public class test.Tiger
Animal
public class test.Cat
Animal
Tiger
Cat
我想把结果做成
public class test.Tiger
Tiger
public class test.Cat
Cat
Tiger
Cat
Java不会为您做这件事,非常简单。您试图让Java执行的操作称为多重调度,Java不支持它。方法参数的类型只在编译时由编译器与参数值匹配,而不是在运行时。在代码中,编译器对参数值最具体的了解是它的类型为Animal
,因此它选择链接到该方法。clazz.cast()
调用没有帮助,因为相同的参数适用于clazz
变量:编译器对它最具体的了解是它是? extends Animal
,因此就编译器而言,cast()
调用的结果属于Animal
类型。
当然,在Java中有一些方法可以达到类似的效果,但我不认为我可以为您选择一种。上面链接的维基百科文章中有一个关于多重调度的例子,你可能也想考虑类似于访问者模式的东西,但不要觉得被模式束缚了。:)