この問題は、インターフェイスの実装が異なる場合に最も明確になり、特定のコレクションの目的では、オブジェクトのインターフェイスレベルのビューのみに関心があります。たとえば、次のようなインターフェースがあるとします。
_public interface Person {
int getId();
}
_
クラスの実装でhashcode()
およびequals()
を実装する通常の方法では、equals
メソッドに次のようなコードが含まれます。
_if (getClass() != other.getClass()) {
return false;
}
_
これにより、Person
の実装をHashMap
に混在させると問題が発生します。 HashMap
がPerson
のインターフェースレベルのビューのみを考慮する場合、実装クラスのみが異なる重複が発生する可能性があります。
すべての実装に同じリベラルequals()
メソッドを使用してこのケースを機能させることはできますが、equals()
が異なるコンテキストで間違った動作をするリスクがあります(比較など) 2つのPerson
s(バージョン番号付きのデータベースレコードによってサポートされます)。
私の直感は、平等はクラスごとではなくコレクションごとに定義する必要があることを教えてくれます。順序に依存するコレクションを使用する場合は、カスタムComparator
を使用して、各コンテキストで正しい順序を選択できます。ハッシュベースのコレクションには類似物はありません。どうしてこれなの?
明確にするために、この質問は「 。equals()がJavaのクラスにあるのに、なぜインターフェースの.compareTo()なのか 」とは異なります。これは、コレクションの実装を扱うためです。 compareTo()
とequals()
/hashcode()
はどちらも、コレクションを使用するときの普遍性の問題に悩まされています。異なるコレクションに対して異なる比較関数を選択することはできません。したがって、この質問では、オブジェクトの継承階層はまったく問題ではありません。重要なのは、比較関数がオブジェクトごとに定義されるか、コレクションごとに定義されるかです。
このデザインは「ユニバーサルエクイティ」として知られています。2つのものが等しいかどうかは、ユニバーサルプロパティであると考えられています。
さらに、等価性はtwoオブジェクトのプロパティですが、オブジェクト指向では、常に1つの単一オブジェクトに対してメソッドを呼び出し、そのオブジェクトはそれを処理する方法のみを決定しますメソッド呼び出し。したがって、Javaのような設計では、等価性は比較される2つのオブジェクトの1つのプロパティであり、対称性などのいくつかの基本的な等価性プロパティを保証することもできません(a == b
⇔b == a
)、最初のケースではメソッドはa
で呼び出され、2番目のケースではb
で呼び出されます。OOの基本原則により、それはa
の決定(最初のケース)またはb
の決定(2番目のケース)は、それ自体が他の1つと等しいかどうかを判断します。対称性を得る唯一の方法は、2つのオブジェクトを連携させることですが、そうでない場合は…頑張ってください。
1つの解決策は、1つのオブジェクトのプロパティではなく、2つのオブジェクトのプロパティまたは3番目のオブジェクトのプロパティを等しくすることです。後者のオプションは、普遍的な同等性の問題も解決します。同等性を3番目の「コンテキスト」オブジェクトのプロパティにすると、コンテキストごとに異なるEqualityComparer
オブジェクトを持つことが想像できるためです。
これはis Haskell用に選択されたデザインで、たとえばEq
タイプクラスを使用しています。これは、一部のサードパーティScalaライブラリ(ScalaZなど))によって選択された設計でもありますが、ユニバーサルを使用するScalaコアまたは標準ライブラリではありません。基盤となるホストプラットフォームとの互換性のための同等性。
興味深いことに、JavaのComparable
/Comparator
インターフェースで選択された設計でもあります。 Java=の設計者は明らかに問題を認識していましたが、何らかの理由で順序付けのためにのみ解決しましたが、等価性(またはハッシュ化)については解決しませんでした。
だから、質問について
なぜ
Comparator
インターフェイスがあるのにHasher
とEquator
がないのですか?
答えは「わからない」です。明らかに、Javaの設計者はComparator
の存在から明らかなように、この問題に気づいていましたが、明らかに等価性とハッシュの問題だとは考えていませんでした。その他言語とライブラリは異なる選択をします。