【问题标题】:How to write a method in superclass whose parameter type is restricted to another object belonging to the same subclass of the calling object如何在超类中编写参数类型限制为属于调用对象的同一子类的另一个对象的方法
【发布时间】:2020-08-31 12:26:43
【问题描述】:

我是 Java 编程新手。请考虑以下代码 sn-p。

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<A extends Animal>、Cat extends Animal<Cat>和mate(A partner)。
  • 怎么样:Animal a = new Cat(); a.mate(new Animal()); 你认为这行得通吗?
  • @Sweeper 如果你能给我一些让它工作的东西就更好了,但我会很高兴只让Cat cat = new Cat(); cat.mate( new Cat() )工作的东西
  • 所以你认为a.mate(new Animal()); 应该编译?我不这么认为。在运行时,a 存储了一个Cat 对象,而Cat 对象不能与Animal 对象匹配,对吧?

标签: java oop polymorphism object-oriented-analysis


【解决方案1】:

没有办法让编译器阻止所有错误调用。即使你参数化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

【讨论】:

    【解决方案2】:

    你的问题是关于多态性。 在 mate 方法中使用超类作为参数类型。超类是动物。 这是代码:

    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.
    

    为了更好地回答而不是说 cat 或 dog ,您可以在 Animal 类中定义一个 name 字段。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-16
      • 2013-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-31
      • 1970-01-01
      相关资源
      最近更新 更多