2011-02-17 6 views
3

私は基本クラスコードにアクセスできません。しかし、サブクラスでもいくつかの基本クラスのプロパティを考慮してequalsを定義できる必要があります。基本クラスはequalsを定義していませんが、サブクラスは必要です。実装方法

さらに、基本クラスには保護されたフィールドがありません。すべてのフィールドは、アクセサ/ミューテータを介してのみアクセスできます。

私のサブクラスの同等の基本クラスフィールドの比較を行うのは悪いと思いますか?どうして ?

私は、基本クラスが私の目的のために働くが、それはまた、サブクラスに等しい行う際に考慮する必要があるフィールドを持っていないデフォルトの等号を持っているので、これを実行する必要があり

...

答えて

6

はい、あなたがこれを行うことができ、限り、あなたが契約に従うよう、あなたが平等にあなたが望む任意の方法を決定することができますよう、あなたのスーパークラスでゲッターを呼び出して何の問題がありません。

再帰:X。 equals(x)はtrueを返す必要があります。

対称:x.equals(Y)== y.equals(X)

推移:x.equals(Y)& & y.equals(Z)=> x.equals( xまたはyが複数の呼び出しの間で変更されない限り、x.equals(y)の複数の呼び出しは一貫してtrueまたはfalseを返します。

とequals-ハッシュコードの契約:

等しいオブジェクトは完全に合理的であると等しいハッシュコード

http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#equals(java.lang.Object)

2

を持っている必要があります。派生クラスの比較を行うときに基底クラスから継承されたプロパティを考慮することには何も問題ありません。基本的に、2つのオブジェクトを比較する場合、重要なのは、その比較の情報がどこに由来するかにかかわらず、選択した定義によって同じであるかどうかです。必要なものを使いましょう。

0

hashCode()もオーバーライドし、問題のプロパティが不変であれば、問題はありません。

時々trueを返し、時にはfalseを返し、その間に誰かがsetXXX()と呼ばれているかどうかに応じて、非常に危険なものであるequals()方法 - それはequals()がために良いものの多くを使用することができません、コレクション内のメンバーシップの決定などです。

java.util.Collectionsのような他のAPIを使用するには、equals()が本当に必要な場合は、UnsupportedOperationExceptionを投げるように変更することをお勧めします。そうでない場合、equals()メソッドは信頼できません。たとえば、次を参照してください。How to use two numbers as a Map key

突然変異子がfinalなら、私はサブクラス化を試みることさえありません。代わりに、私は 'スーパークラス'オブジェクトからの値を自分のフィールドにコピーして元のものを投げ捨てます。 (プライベートフィールドであっても、それを保持しておけば、他の誰かにそれを参照せずに変異させることはできません。) 'スーパークラス'を必要とするAPIと相互運用するために 'サブクラス' 「スーパークラス」オブジェクトをオンザフライで生成するメソッドasXXX()を含める必要があります。

あなたは自分自身の目的のために等価を決定する必要がある場合はそれ以外の場合は、私はすべてequals()/hashCode()をオーバーライドし、代わりに新しいメソッドを作成し、isEquivalentTo()のようなもの、それを呼び出すことはありません。

+0

HashMap *でキーとして使用されているときに*変更されていない*ビットが変更されていない*が不変であることを緩和することができますが、これを文書化してください(equals、hashCode、ミューテーターメソッド)。 –

+0

個人的には、私はこのような場合にスクラップを防ぐための文書化の能力に疑念を持っていますが、YMMV。 –

0

equalsのオーバーライドには特に問題はありません。あなたが行う必要がある場合は、ゲッターを介してプライベートメソッドにアクセスすることは間違いありません。

ただし、基本クラスに子クラスを置き換え、動作の概念的な変更を取得できないようにするLiskov Substitutionの原則に関連する、わずかな概念上の問題があります。

実装しているequals()がという概念的にで、基底クラスで実装されているequalsと大きく異なる場合、コードを使用している人(メンテナなど)は理解しづらいでしょう。彼らは特定の仮定に基づいてコード化し、それらの仮定は間違ったものになるでしょう。ベースが等しい場合たとえば、()、参照平等にすなわち

equals(Object o) { return this == o;} 

をベースとしており、あなたの実装では、ユーザーは、彼らが必要以上に特定implemntationについての詳細を知ることは非常に違うものが必要になりますありません。対称性にも違反します.xがあなたの子クラスで、yが基本クラスであれば、x.equals(y)はy.equals(x)と同じになりません。

これらのどれも耐えることはできないと言われていますが、ベースを変更できない場合は選択肢がありません。あなたのクラスにたくさんのコメントを追加してください。

+0

対称性について:新しいequalsメソッドは、他のオブジェクトもサブクラスのオブジェクトである場合にのみtrueを返すことを確認してください。 –