pro*_*nda 5 java sorting inheritance
假设a Superclass implements Comparable<Superclass>,Arrays.sort(ArrayOfSuperInstances);使用此compareTo(Superclass other)方法进行排序.这是否可以保证一组实例Subclass extends Superclass将以相同的方式排序Arrays.sort(ArrayOfSubInstances);?(假设compareTo在子类定义中没有重载)
或者换句话说,Subclass默认情况下会继承它的compareTo方法Superclass,以便人们可以盲目地使用Arrays.sort()知道它们将被排序为超类吗?
是的 - 这是多态性背后的整个原则,特别是Liskov替代原则.基本上,如果A是B的子类,那么你应该能够在任何你能够使用B的地方使用A,并且它应该基本上与B的任何其他实例(或B的其他子类)相同.
所以,它不仅会发生,而且几乎总是你想要发生的事情.compareTo在子类中通常是错误的.
为什么?那么,Comparable<T>合同的一部分是比较是可传递的.由于你的超类可能不知道它的子类在做什么,如果一个子类compareTo以这样的方式覆盖它给出的答案不同于它的超类,它就会破坏契约.
例如,假设你有像Square和ColorSquare这样的东西.Square compareTo比较两个方块的大小:
@Override
public int compareTo(Square other) {
return this.len - other.len;
}
Run Code Online (Sandbox Code Playgroud)
...而ColorSquare也增加了颜色的比较(让我们假设颜色是可比较的).Java不会让你拥有ColorSquare工具Comparable<ColorSquare>(因为它的超类已经实现了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;
}
Run Code Online (Sandbox Code Playgroud)
这起初看起来很无辜.如果两个形状都是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!
Run Code Online (Sandbox Code Playgroud)