使用される同等性の概念を定義するクラス。
オブジェクトが平等の汎用概念を定義する場合、そのジョブの一部として、それに対応するハッシュコードを定義する必要があります。
結局のところ、、、、、または何が定義されているかEquals()
を「知っている」のはそのクラスです。その場合、それができる唯一のクラスである必要があります。isEqual()
areEqual
==
a == b
hash(a) == hash(b)
ただし、別のクラスが同等性の概念を定義している場合(おそらく、さまざまな方法で別のクラスを使用し、文字列が等しいかどうかを判断するさまざまな方法が典型的な例です)、そのクラスは同様の理由でハッシュコードを定義する必要があります。
.NETは、例として、この責任のリンクを表現しています。.NETでは、すべてのオブジェクトに。がありEquals()
ます。それが良いことであるかどうかは議論の余地がありますが(オブジェクトが他のオブジェクトと同等であるという感覚を必要としないC ++アプローチを好む人もいます)、一度実行すると、すべてのオブジェクトにもが含まれることは理にかなっていますGetHashCode()
。一方と他方。.NETには、クラスが特定の組み込みされていない平等の感覚に責任を持つための手段を定義するものもありますIEqualityComparer<T>
。IEqualityComparer
ここでも、一方の責任を取るには、もう一方の責任を取る必要があります。
今。どちらが良いですか?
さて、与えられた場合に「等しい」が何を意味するかという圧倒的に明白な感覚がある場合、それはおそらくクラスによって処理されるべきです:同じ座標または同じ複素数の2つの表現、または同じ実数を参照するワールドオブジェクトは、おそらくほとんどの場合等しいと見なされるべきです。したがって、デフォルトで使用されます。
特定のコンテナタイプのコンテキストで等しいとはどういう意味かという圧倒的に明白な意味がある場合は、そこに適用する必要があります。
それ以外の場合は、それを定義するコネクタが必要です。したがって、関心の分離をうまく行うことができます。
ただし、3つを非常にきれいに結び付けることができます。デフォルトのコネクタを定義します。その実装は、ハッシュコードを取得するための呼び出しを渡すか、オブジェクトで定義されたものと等しいかどうかをテストするだけです。
汎用ハッシュテーブル、ハッシュセットなどを定義して、常にコネクタを使用します。デフォルトは構築時またはデフォルトのテンプレートパラメータです(言語にこれを可能にするジェネリック/テンプレートアプローチのようなものがある場合、たとえばC ++たとえば、C#はしますが、しません)。そのため、デフォルトでは、このデフォルトのコネクタを使用しています。
コンセプトの特定のビューに依存する特別な目的のコレクションタイプを定義する場合、それらのコレクションの1つから構築し、コネクタをオーバーライドします。
このルールの裏側は、すべての同等のオブジェクトがハッシュコードを提供するための定義された手段がない場合(たとえば、==
オーバーライドメカニズムはあるが、の深いサポートがないGetHashCode()
場合)、コネクタを使用する必要があることです。アプローチ。たとえば、C ++にはがあり==
ますが、特定のオブジェクトを持つ方法を知るためのそのようなサポートはありません。したがって、STLにはが必要でhash_map
あり、すぐに使用できるデフォルトのサポートは非常に限られています。