異なるinstanceに対して複数のinstanceofテストによるequals()をオーバーライドすることは可能でしょうか?

複数の異なるタイプのオブジェクトを調べなければならないクラスがあるとします。 equals()を次のようにオーバーライドすることは可能か可能か

public boolean equals(Object o){
    if(o == null) return false;
    if(o instanceof class1){
        return this.class1.equals((class1) o);
    if(o instanceof class2){
        return this.class2.equals((class2) o);
    ...

}

これはこれまでに役立つだろうか?ここでは、それぞれのクラスに静的なオーバーロードされたequals()メソッドを作成することを前提としています(ただし、キャストしていれば多態性が自動的に処理されます)。

1
追加された 著者 Raedwald,
そのコードは合法であるため、可能です。しかし、同じクラスであれば、2つのオブジェクトが等しいと言うことは良い考えではありません。このような実験を実装することに決めた場合、OOでそれを行う適切な方法は、各サブクラスでequalsをオーバーライドすることです。
追加された 著者 Mister Smith,
あなたの素晴らしいコメントをありがとう。
追加された 著者 user991710,
@CedricMartin真実ではありません。等価性を変更するサブクラスに属性を追加することはできません。まあ、以前の文章も間違っています:equalsを正しく実装することができます(つまり、等価関係の保証された数学的特性に違反することなく)。それでも誰もが望むものではないので実用的価値はほとんどありません。実際、オデスキーはそれを行う方法を示す記事を書いた。編集:またはあなたは、サブクラスが正しく実装することを保証できないと言っているだけですか?本当ですが、同じことが私が言っていることの多くのものに当てはまります。
追加された 著者 Voo,
@CedricMartin Oderskyはまだequalsを使用していますが、ヘルパーメソッドを使用しています。そして、私はそのようなやり方で行動を変えずにうまく動作するサブクラスを書いていることを確かめました。そして、私が属性を追加し、サブクラスで親クラスと比較したとき常に非等価であると評価した状況でも。しかし、その根本的な問題をどうやって解決しますか?私はあなたがequalsを実装する場所がどのように重要であるか分かりません。スーパークラスとサブクラスを比較するとすぐに、それらの問題がちょっと這い上がります。提案された解決策は何ですか?
追加された 著者 Voo,
@CedricMartinいいえ、私たちはそれによって過渡性を打破しません。等比関係が持つべきあらゆる数学的性質が保証されます。はい、私たちはequalsを上書きするたびに追加メソッドが必要です。はい、ソリューションは必ずしも直感的ではありません - そして?あなたのソリューションが「まあまあ平等ではない」の場合は、何も使用しない代わりに、「完璧ではない解決策」を使うと思います。ハッシュマップ、順序付けされたコレクション、そして2つの方法が必要な場所がない、実際のOOPの土地でプログラムするのは楽しいものでなければなりません。私は実用的な解決法を好むと思う。
追加された 著者 Voo,
あなたがやっていることに応じて「役に立つ」ことができますが、Javaの階層の最上位で equals hashCode を持つことは、純粋かつ単純に欠陥があることを知る必要があります。その周りには道はない。継承を持つとすぐに、equals/hashcodeコントラクトを保証することはできません。それと同じくらい簡単です。 不可能。これは、Joshua Blochが Effective Java でうまくはっきりと明白に説明されています。 Artimaのこのテーマについては、Martin Odersky(Scalaの名声から)の素晴らしい話もあります。
追加された 著者 Cedric Martin,
@Voo:Oderskyは、ある日、問題を回避するために、equals()やhashCode()を使わずに(他のメソッドを作成している)記事を書いた。 Joshua Blochは次のように述べています。「インスタンス化可能なクラスを拡張し、等価な契約を保持しながらアスペクトを追加する方法はありません」したがって、継承を使用する場合(通常、クラスとサブクラスを持つことを意味します)、OO階層の最上部に hashCode という継承を使用する場合は、 Javaで壊れています。私は対処方法があると論争しません:私は単に equals hashCode は存在してはいけないと述べています。
追加された 著者 Cedric Martin,
@Voo:例えば、手続き的な方法でJavaを使用し、コレクション内に常に同じ種類のオブジェクトを置いて、 equals を指定するなど、オブジェクト指向をしないと、 ) "サブクラスにアスペクト/属性を追加しないとできます" しかし、実際には継承とオブジェクト指向について話しています。 hashCode !?
追加された 著者 Cedric Martin,
@Voo: "また、属性を追加してサブクラスで常に評価が等しくない" の場合でも、Transient( Effective Java )が破られました。 Joshua BlochがEffective Javaに書いた正確な文章をもう一度述べておきます:「インスタンス化可能なクラスを拡張し、等価な契約を維持しながらアスペクトを追加する方法はありません」 。ジョシュア・ブロッホと議論することができます:あなたはイコール契約を破ってしまった。提案された解決策? equals hashCode が壊れていることを認めて、それらの使用をやめたり、OOをやっていると思わないようにしてください。
追加された 著者 Cedric Martin,
@Voo:Odersky氏のソリューションは完璧ではないことを指摘するのも便利です(ヘルパーメソッドを使っていないので、equalsとequalsのすべてのオブジェクトに存在するメソッドを使用しています)。 hashCodeは存在します)。それをやめて!
追加された 著者 Cedric Martin,

4 答え

I very much doubt that because you can easily violate the transitivity of equals this way (x.equals(y) && x.equals(z) implies y.equals(z))

当然のことながら、あなたはすべてのクラスを含む非常にセットアップを行いますが、それは正しいことに苦労するでしょう

3
追加された
あまりにも複数の回答を選ぶことはできません!
追加された 著者 user991710,

指定されたオブジェクトが受信機のさまざまなメンバー変数の少なくとも1つと等しいかどうかをチェックするメソッドが必要なようです。

java.lang.Object#はこの目的のために等しくなります。

代わりに、別の方法を提供する必要があります。

public boolean hasEquals(Object o) {//your impl }
1
追加された

意味的には、これは良い考えだとは思わない。等価はクラス型に基づいてはならず、インスタンス変数に基づいているべきです。 それとは別に、Appleは決して梨と同じではなく、他のりんごにしかならないはずです。

1
追加された

相互再帰に至らないことが確実であれば、 that.equals(this)を返すことができます。しかし、一般的に、オブジェクトの平等は、クラスの平等、または少なくともそれらの間の一貫した継承関係を意味します。

0
追加された