簡単な質問:Javaがequals()
のオーバーライドを許可するのはなぜですか?なぜそれが最終的ではないのですか?
私は効果的なJava第2版をJoshua Blochで読んでいます。私はその結論に少し困惑しています。
等しいコントラクトを維持しながら、インスタンス化可能なクラスを拡張して値コンポーネントを追加する方法はありません
equals()
はfinal
メソッドであるべきだと言っているのではありませんか?
この本は、equals()
メソッドを持つクラスA
の例と、AX
のequals()
メソッドとは異なる独自のequals()
メソッドを持つA
を拡張するクラスA
の例を示しています。
A
のequals()
とAX
のequals()
の詳細については触れませんが、異なるであると言えば十分です。したがって、いくつかのコンテキスト(特にA
、HashSet
タイプ)でHashMap
の異なる実装を混合すると、equals()
の推移性や対称性(おそらく他の何か)の違反を保証する相互運用性の問題があります。
さらに考えてみると、次のようなものがあるという結論には同意できないと思います。
public boolean equals(Object o) {
if (o == null || o.getClass() != getClass())
return false;
...
}
間違っている。これは、equals()
のオーバーライドを処理するための適切な方法だと思います。
Javaはそれを可能にするので、Javaは理由のためにequals()
をオーバーライドすることを許可します。厳密な意味でリスコフの置換原則を考慮に入れていたなら、equals()
そして暗黙的にequals()
の実装をコンパイラレベルでfinalにします。あなたはどう思いますか?
構成が単に適切ではない場合を考えることができ、equals()
をオーバーライドするのが最良のオプションです。これは、クラスA
をデータベースで永続化する場合であり、コンテキストは、A
の実装とA
のサブクラス(AX
など)の両方を持つコレクションがないことを意味します。
あなたの論理に対する単純な議論は、それがファイナルになるように変更された場合のequalsメソッドの使用方法です。次に、任意のオブジェクトに対して同じロジックを実行します。オブジェクトクラスのAとAXを比較したい場合、ロジックは何でしょうか?
Finalメソッドのオーバーライドにより、定義されたロジックに基づいて、2つの異なるオブジェクト(2つの異なるメモリ位置に存在する)が実際に等しいかどうかを検証できます(==メソッドは2つの参照が同じオブジェクトのものであるかどうかをチェックするためにあります)。たとえば、このようなユーザーオブジェクトがある場合、
User
{
string name;
string email;
string phone;
}
1つのシステムでは、ユーザーを一意に識別するために関心を持つ可能性のある電子メールになります。したがって、メールの値に基づいて比較できます。ただし、他のシステムでは、一意の識別子として電話を使用する場合があります。したがって、彼らは異なる等しいメソッドを実装することを決定するかもしれません。
A、AXおよびLiksovの置換原則の論理に関しては、
基本クラスへのポインタまたは参照を使用する関数は、それを知らなくても派生クラスのオブジェクトを使用できる必要があります。
そうするなら、
AX ax1 = new AX();
AX ax2 = new AX();
ax1.equals(ax2);
そして
A a = new AX();
AX ax = new AX();
a.equals(ax);
同じ出力が得られるはずです。
あなたの短い質問に短い答えを与えるために-それはJava.lang.Objectのために定義されたequals()関数がほとんど役に立たないからです。 2つの参照が同じオブジェクトを参照している場合はtrueを返し、Wordの通常の意味で「等しい」かどうかを実際にテストしないという点で、「==」とまったく同じです。
したがって、実際に2つのオブジェクトを比較して、それらが等しいデータを保持しているかどうかを確認する場合は、equals()のデフォルトの実装をオーバーライドする必要があります。通常、hashCode()もオーバーライドする必要があります。