はい - それがポリモフィズムの背後にある原理全体であり、具体的にはリスコフ置換原理です。基本的に、A が B のサブクラスである場合、B を使用できる場所ならどこでも A を使用でき、基本的に B の他のインスタンス (または B の他のサブクラス) と同じように動作する必要があります。
ですから、それが起こるだけでなく、ほとんどの場合、あなたが望んでいることです。通常compareTo
、サブクラスでは間違っています。
なんで?まあ、Comparable<T>
契約の一部は、比較が推移的であるということです。スーパークラスはおそらくそのサブクラスが何をしているかを知らないため、サブクラスがcompareTo
そのスーパークラスとは異なる答えを与えるような方法でオーバーライドすると、契約が破られます。
たとえば、Square と ColorSquare のようなものがあるとします。Square'scompareTo
は、2 つの正方形のサイズを比較します。
@Override
public int compareTo(Square other) {
return this.len - other.len;
}
...一方、ColorSquare は色の比較も追加します (色が Comparable であると仮定しましょう)。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;
}
これは一見無害に見えます。両方の形状が 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!