PartialEq în Rust

Trait-ul din spatele operatorilor == și !=; derive compară toate câmpurile, implementarea manuală alege criteriul.

Sintaxă
#[derive(PartialEq)]
struct Tip { ... }

pub trait PartialEq<Rhs = Self> {
    fn eq(&self, other: &Rhs) -> bool;
    fn ne(&self, other: &Rhs) -> bool { !self.eq(other) }
}

Ce face PartialEq

Ca să poți scrie a == b, tipul trebuie să implementeze PartialEq. #[derive(PartialEq)] consideră două valori egale când toate câmpurile sunt egale (la enum-uri: aceeași variantă și aceleași date). != vine automat din eq.

Implementarea manuală îți permite alt criteriu: două persoane sunt egale dacă au același CNP, două e-mailuri sunt egale ignorând literele mari. Parametrul Rhs permite chiar compararea cu alt tip (impl PartialEq<&str> for Oras), cum face String == &str.

„Partial” înseamnă că o valoare poate să nu fie egală cu ea însăși: f64::NAN == f64::NAN este false. Tipurile fără această problemă implementează și Eq.

Parametri

Parametru Descriere
eq(&amp;self, other) Singura metodă obligatorie: true dacă valorile sunt egale.

Ce returnează

bool.

Exemple

Exemplul 1: derive(PartialEq) pe struct și enum

#[derive(Debug, PartialEq)]
enum Plata {
    Numerar,
    Card { ultimele4: u16 },
}

#[derive(Debug, PartialEq)]
struct Comanda {
    id: u32,
    plata: Plata,
}

fn main() {
    let a = Comanda { id: 7, plata: Plata::Card { ultimele4: 1234 } };
    let b = Comanda { id: 7, plata: Plata::Card { ultimele4: 1234 } };
    let c = Comanda { id: 7, plata: Plata::Numerar };
    println!("a == b: {}", a == b);
    println!("a == c: {}", a == c);
    println!("a != c: {}", a != c);
    let nan = f64::NAN;
    println!("NaN == NaN: {}", nan == nan);
}

Rezultat

a == b: true
a == c: false
a != c: true
NaN == NaN: false

Exemplul 2: Egalitate după CNP și comparare cu &str

struct Persoana {
    cnp: String,
    nume: String,
}

impl PartialEq for Persoana {
    fn eq(&self, other: &Self) -> bool {
        self.cnp == other.cnp          // numele nu contează
    }
}

impl PartialEq<&str> for Persoana {
    fn eq(&self, other: &&str) -> bool {
        self.cnp == *other
    }
}

fn main() {
    let a = Persoana { cnp: "2900101223344".into(), nume: "Ana Pop".into() };
    let b = Persoana { cnp: "2900101223344".into(), nume: "Ana Popescu".into() };
    println!("{} == {}: {}", a.nume, b.nume, a == b);
    println!("după CNP: {}", a == "2900101223344");
}

Rezultat

Ana Pop == Ana Popescu: true
după CNP: true

Greșeli frecvente

  • Compari un tip propriu cu == fără PartialEq: binary operation `==` cannot be applied to type.
  • Implementezi PartialEq manual, dar lași #[derive(Hash)]: valori egale pot avea hash-uri diferite și HashMap se comportă greșit. Când schimbi egalitatea, schimbă și Hash.

Comenzi înrudite

  • Eq: Trait marker care promite egalitate completă (a == a mereu); cerut de chei în HashMap/HashSet și de Ord.
  • PartialOrd: Trait-ul din spatele operatorilor <, >, <=, >=; partial_cmp poate returna None (ex. NaN la f64).
  • Hash: Trait-ul care transformă o valoare într-un hash; necesar (alături de Eq) pentru chei în HashMap și HashSet.
  • Ord: Ordonare totală: orice două valori se pot compara. cmp() returnează Ordering; necesar pentru sort(), BTreeMap, max().