假设一个 Superclass implements Comparable<Superclass>
, 这样 Arrays.sort(ArrayOfSuperInstances);
使用这个 compareTo(Superclass other)
方法进行排序。这是否保证 Subclass extends Superclass
的实例数组?将使用 Arrays.sort(ArrayOfSubInstances);
以相同的方式排序? (假设子类定义中没有重载compareTo)
或者换句话说,将Subclass
默认继承 compareTo
其方法Superclass
, 这样就可以盲目使用 Arrays.sort()
知道它们将被排序为父类(super class)?
最佳答案
是的——这就是多态背后的全部原则,特别是 Liskov substitution principle .基本上,如果 A 是 B 的子类,那么您应该能够在任何可以使用 B 的地方使用 A,并且它的行为本质上应该与 B 的任何其他实例(或 B 的其他子类)相同。
因此,它不仅会发生,而且几乎总是您希望发生的事情。 compareTo
通常是错误的在子类中。
为什么?嗯,一部分Comparable<T>
契约是比较是传递的。因为你的父类(super class)可能不知道它的子类在做什么,如果一个子类覆盖了 compareTo
以这种方式给出不同于其父类(super class)的答案,它违反了契约。
例如,假设您有 Square 和 ColorSquare 之类的东西。四方的compareTo
比较两个正方形的大小:
@Override
public int compareTo(Square other) {
return this.len - other.len;
}
...而 ColorSquare 还添加了颜色比较(假设颜色是可比较的)。 Java 不会让您拥有 ColorSquare 工具 Comparable<ColorSquare>
(因为它的父类(super class)已经实现了 Comparable<Square>
),但是你可以使用反射来解决这个问题:
@Override
public int compareTo(Square other) {
int cmp = super.compareTo(other);
// don't do this!
if (cmp == 0 && (other instanceof ColorSquare)) {
ColorSquare otherColor = (ColorSquare) other;
cmp = color.compareTo(otherColor.color);
}
return cmp;
}
乍一看这看起来很无辜。如果两个形状都是 ColorSquare,它们将比较长度和颜色;否则,他们只会比较长度。
但是如果你有:
Square a = ...
ColorSquare b = ...
ColorSquare c = ...
assert a.compareTo(b) == 0; // assume this and the other asserts succeed
assert a.compareTo(c) == 0;
// transitivity implies that b.compareTo(c) is also 0, but maybe
// they have the same lengths but different color!
assert b.compareTo(c) == 1; // contract is broken!
关于java - 在 Java 中对子类进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11928656/