如何在超类中编写方法,该方法的参数类型仅限于属于调用对象的同一子类的另一个对象

问题描述

我是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类中定义一个名称字段。