W Rust trait'y PartialEq i Eq wynikają z filozofii bezpieczeństwa typów — wszystkie fundamentalne operacje dla kolekcji (HashMap, HashSet) opierają się na ścisłym określeniu równości. Trait'y definiują, czy obiekty dwóch typów mogą być porównywane za pomocą == oraz czy typ jest zobowiązany do implementacji "pełnego" równości (Eq) lub "częściowego" (PartialEq).
Nieprawidłowa implementacja PartialEq/Eq prowadzi do niepoprawnego działania kolekcji, gdzie naruszane są podstawowe właściwości matematyczne: porównanie ze sobą, symetria, przechodniość. Ponadto, nieprawidłowy Eq może prowadzić do "zgubienia" obiektów w kolekcjach lub pojawienia się nieoczekiwanych duplikatów.
PartialEq jest implementowany dla typów, w których porównanie nie jest możliwe dla wszystkich wartości (na przykład, f32, gdzie NaN != NaN). Eq jest przeznaczony tylko dla "ścisłych" (całkowitych) relacji. Typy użytkownika powinny implementować porównanie w ścisłej zgodności z tymi kontraktami.
Przykład kodu:
#[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
Kluczowe cechy:
Dlaczego dla typu f32 standardowa biblioteka implementuje tylko PartialEq, ale nie Eq?
Ponieważ według IEEE-754 NaN != NaN, tzn. właściwość x == x dla wszystkich x nie jest przestrzegana, a jest to niezbędna właściwość dla Eq.
Czy konieczne jest jawne implementowanie Eq, jeśli PartialEq jest zaimplementowany ręcznie?
Tak, jeśli typ wspiera pełną równość (x == x zawsze true), należy ręcznie zaimplementować również Eq, w przeciwnym razie niektóre struktury nie skompilują się z twoim typem.
Czy użytkownik może zaimplementować PartialEq "niesymetrycznie" (x == y, ale y != x)?
Technicznie tak, ale prowadzi to do niepoprawnego działania kolekcji i jest uważane za błąd.
** Negatywny przypadek
Użytkownik zaimplementował PartialEq dla typu, porównując tylko po jednym polu, a pozostałe są ignorowane. W wyniku HashSet "traci" duplikaty.
Plusy:
Minusy:
** Pozytywny przypadek
Używa #[derive(PartialEq, Eq)] lub implementuje własną wersję porównania, uwzględniającą całą logikę biznesową, zapewniającą wymagane właściwości.
Plusy:
Minusy: