2

为了从概念上理解继承、接口和多态性,我创建了几个类来测试事物。我得到的结果不是我所期望的。代码如下:

public class Animal implements Comparable{
//Animal constructor & methods
public int compareTo(Object arg0){System.out.println("Animal.compareTo");}
}

public class Bear extends Animal{
//Bear constructor & methods
}

public class PolarBear extends Bear implements Comparable{
//PolarBear constructor & methods
public int compareTo(Object arg0) {System.out.println("PolarBear.compareTo");

我没有收到任何错误说我无法再次实现 Comparable。但是在我的测试中,一旦我创建了 PolarBear,我就无法回到 Animal 的 compareTo 方法,即使 PolarBear 应该继承 Animal 的 compareTo。我测试了以下内容:

Animal bobo = new PolarBear();
bobo.compareTo(null);
((PolarBear) bobo).compareTo(null);
((Animal)bobo).compareTo(null);
((Comparable) bobo).compareTo(null);    

他们每个人都打印了:

 PolarBear.compareTo

有什么方法可以访问Animal'scompareTo吗?从逻辑上讲,我不希望能够比较 a 的动物品质PolarBear以及PolarBear品质吗?

4

4 回答 4

7

bobo将对象转换为PolarBearAnimal或并不重要,对象Comparable的运行时类型将始终是PolarBear,因为您将其实例化为

Animal bobo = new PolarBear();

因此,无论何时调用.compareTo(wtv)它都会调用PolarBear实现。

这就是多态性。阅读后期绑定,因为这就是多态在 java 中的实现方式。

如果要调用compareTo(wtv)父类的方法,则必须super.compareTo(wtv)在任何其他子类的方法中进行。

于 2013-01-09T16:47:12.860 回答
2

compareTo 和继承通常是一件棘手的事情。从理论上讲,拥有 Comparable 具体超类的子类会破坏可比合同。例如 - 假设我有一个超类 A,它通过检查字段 a1 和 a1 与其他 A 进行比较。现在让我们添加一个具有额外字段 b1 的子类 B。anA.compareTo(aB)将通过 a1 和 a2 进行比较,而((A)aB).compareTo(anA)不会与
您的问题相同-您可以通过执行类似的操作仅从子类本身调用 compareTo 的 Animal 版本

super.compareTo(<something>)

但不是来自“外部”,因为您已经覆盖了该方法。您有责任与外部世界保持与您刚刚覆盖的方法相同的“合同”。

于 2013-01-09T16:46:13.473 回答
1

您可以随时从 PolarBear 中调用super.compareTo(arg0)来调用 Animal.compareTo 中的逻辑。

于 2013-01-09T16:43:50.503 回答
0

这很简单。底层对象是 PolarBear 类,您每次都在更改对象的接口(用于保存对象引用的类)。

JVM 在编译时检查接口中的方法(用于保存对象引用的类)是否存在,但绑定发生在运行时,因为 Child (PolearBear) 具有该方法,因此它将始终运行该方法。

使用 super.compareTo() 来调用父方法。

于 2013-01-09T16:58:46.510 回答