Rustにおいて、PartialEqとEqトレイトは型安全性の哲学から生まれており、すべてのコレクション(HashMap、HashSet)にとって基本的な操作は厳密な等価性の定義に基づいています。これらのトレイトは、2つの型のオブジェクトが==によって比較できるかどうか、また型が「完全」な等価性(Eq)または「部分的」な等価性(PartialEq)を実装する義務があるかどうかを定義します。
PartialEq/Eqの不適切な実装は、自己比較、対称性、推移性の基本的な数学的性質が損なわれ、コレクションの誤動作を引き起こします。また、不適切なEqは、オブジェクトがコレクション内で「失われる」または予期しない重複が発生する原因となる可能性があります。
PartialEqは、比較が可能でないすべての値に対して機能する型(例えば、f32、NaN != NaN)のために実装されます。Eqは「厳密な」(全体的な)関係のために設計されています。ユーザー定義の型は、これらの契約に厳密に従って比較を実装する必要があります。
コードの例:
#[derive(PartialEq, Eq)] struct Point { x: i32, y: i32, } let p1 = Point { x: 1, y: 2 }; let p2 = Point { x: 1, y: 2 }; assert!(p1 == p2); // true
主な特徴:
なぜf32型には標準ライブラリがPartialEqのみを実装し、Eqを実装していないのですか?
IEEE-754により、NaN != NaNであるため、すべてのxに対してx == xの性質が遵守されないからであり、これはEqのために必要な性質です。
PartialEqが手動で実装されている場合、Eqを明示的に実装する必要がありますか?
はい、型が完全等価性(x == xが常にtrue)をサポートする場合、手動でEqも実装する必要があります。さもなくば、いくつかの構造体はあなたの型でコンパイルを拒否します。
ユーザーはPartialEqを「非対称」に実装できますか?(x == yだがy != x)
技術的には可能ですが、これはコレクションの誤動作を引き起こし、バグとみなされます。
** ネガティブケース
ユーザーが1つのフィールドに基づいてのみ比較するPartialEqを実装し、残りを無視した結果、HashSetが重複を「失う」ことになります。
利点:
欠点:
** ポジティブケース
#[derive(PartialEq, Eq)]を使用するか、ビジネスロジック全体を考慮した独自の比較バージョンを実装し、必要な性質を保証します。
利点:
欠点: