问题描述
我是Java编程的新手。请考虑以下代码段。
public class Animal {
public void mate( /*what should I put here?*/ anotherAnimal ) {
}
}
public class Cat extends Animal {
}
public class Dog extends Animal {
}
我想以这样一种方式编写方法Animal.mate()
:从子类对象调用该方法时,馈给该方法的参数必须是同一子类的对象,否则会出现编译器错误触发。例如:
Cat cat = new Cat();
Dog dog = new Dog();
Animal randomAnimal = new Animal();
Cat truelove = new Cat();
cat.mate( dog ); // raises a compiler error
cat.mate( randomAnimal ); //compiler error
cat.mate( truelove ); //passes compiler check
我要问的可能吗?我有一种模糊的感觉,也许可以使用泛型来实现。
解决方法
无法使编译器阻止所有错误的调用。即使您对Animal
进行了参数设置,也可能在运行时执行类似cat.mate(dog)
的操作。
如果您的业务逻辑要求这样做,那么最好的选择是使用类似 这样的东西进行验证:
public class Animal {
public final void mate(Animal anotherAnimal ) {
if(!this.getClass().equals(anotherAnimal.getClass())) {
throw new IllegalArgumentException();
}
}
}
如果您这样做主要是为了改善编译时类型检查,则可以使用泛型,但要了解其局限性:
class Animal<T extends Animal<T>> {
public final void mate(T anotherAnimal) {
}
}
如果您的API用户使用子类而不是Animal
类型,并且他们不使用原始类型,那么这将起作用。
Cat c = new Cat();
c.mate(new Cat());
c.mate(new Dog());//fails
Animal animal = c; //raw type
animal.mate(new Dog()); //only a warning
,
您的问题即将发生多态。 在匹配方法中使用超类作为参数类型。超类是动物。 这是代码:
public class Animal {
public void mate(Animal animal) {
System.out.println("Animals mating");
}
@Override
public String toString() {
return "Animal";
}
public class Dog extends Animal {
@Override
public String toString() {
return "Dog";
}
public class Cat extends Animal {
@Override
public void mate(Animal obj) {
System.out.println("cat mating with " + obj );
}
@Override
public String toString() {
return "cat";
}}
并在main方法中运行您的代码。错误已经消失,这就是答案:
cat mating with Dog.
cat mating with Animal.
cat mating with cat.
要获得更好的答案,不必说猫或狗,您可以在Animal类中定义一个名称字段。