Gleichheits-Traits
Teil des Abschnitts Object Oriented Programming der Rust-Journey von Coddy — Lektion 38 von 61.
Das Vergleichen zweier Instanzen eines benutzerdefinierten Structs mit == funktioniert in Rust standardmäßig nicht. Der Compiler weiß nicht, wie er feststellen soll, ob zwei Structs gleich sind – Sie müssen es ihm mitteilen, indem Sie das PartialEq-Trait implementieren.
Wie Debug und Copy kann man PartialEq automatisch ableiten:
#[derive(PartialEq)]
struct Coordinate {
x: i32,
y: i32,
}
let a = Coordinate { x: 5, y: 10 };
let b = Coordinate { x: 5, y: 10 };
let c = Coordinate { x: 3, y: 7 };
println!("{}", a == b); // true
println!("{}", a == c); // false
Wenn es abgeleitet wird, vergleicht PartialEq jedes Feld des Structs. Zwei Instanzen sind nur dann gleich, wenn alle ihre entsprechenden Felder übereinstimmen.
Sie werden auch auf Eq stoßen, was ein Marker-Trait ist, der totale Gleichheit anzeigt – was bedeutet, dass jeder Wert sich selbst entspricht. Die meisten Typen erfüllen dies, aber Gleitkommazahlen nicht (da NaN != NaN). Für Structs mit Integer-Feldern können Sie sicher beides ableiten:
#[derive(PartialEq, Eq)]
struct Coordinate {
x: i32,
y: i32,
}
Eq besitzt keine eigenen Methoden – es signalisiert lediglich, dass der Typ reflexive Gleichheit besitzt. Einige Funktionen der Standardbibliothek erfordern Eq zusätzlich zu PartialEq, daher ist es üblich, beide zusammen für Typen abzuleiten, die dafür infrage kommen.
Aufgabe
EinfachLassen Sie uns ein Farbabgleichssystem erstellen, das zeigt, wie die Traits PartialEq und Eq den Vergleich zwischen Struct-Instanzen ermöglichen!
Sie werden zwei Dateien erstellen, um Ihre Farbabgleichslogik zu organisieren:
color.rs: Definieren Sie ein öffentlichesColor-Struct mit drei öffentlichen Feldern:red,greenundblue(alleu8). Leiten Sie sowohlPartialEqals auchEqab, damit zwei Farben mit==verglichen werden können. Wenn diese abgeleitet sind, betrachtet Rust zwei Farben nur dann als gleich, wenn alle drei RGB-Komponenten exakt übereinstimmen.main.rs: Binden Sie Ihr Farbmodul ein und erstellen Sie zweiColor-Instanzen unter Verwendung der bereitgestellten Eingaben. Vergleichen Sie diese mit==und geben Sie aus, ob sie übereinstimmen oder nicht.
Ihre Ausgabe sollte angeben, ob die beiden Farben gleich sind:
Color 1: rgb({r1}, {g1}, {b1})
Color 2: rgb({r2}, {g2}, {b2})
Colors match: {true/false}Zum Beispiel mit den Eingaben 255, 128, 0, 255, 128, 0:
Color 1: rgb(255, 128, 0)
Color 2: rgb(255, 128, 0)
Colors match: trueUnd mit den Eingaben 100, 100, 100, 200, 200, 200:
Color 1: rgb(100, 100, 100)
Color 2: rgb(200, 200, 200)
Colors match: falseSie erhalten sechs Eingaben: die RGB-Werte für die erste Farbe (drei Werte), gefolgt von den RGB-Werten für die zweite Farbe (drei Werte). Parsen Sie jeden Wert als u8.
Spickzettel
Um benutzerdefinierte Structs mit == zu vergleichen, implementieren Sie das PartialEq-Trait, indem Sie es ableiten (deriven):
#[derive(PartialEq)]
struct Coordinate {
x: i32,
y: i32,
}
let a = Coordinate { x: 5, y: 10 };
let b = Coordinate { x: 5, y: 10 };
println!("{}", a == b); // true
Wenn es abgeleitet wird, vergleicht PartialEq alle Felder – zwei Instanzen sind nur dann gleich, wenn alle entsprechenden Felder übereinstimmen.
Das Eq-Trait ist ein Marker-Trait, das totale Gleichheit anzeigt (jeder Wert ist gleich sich selbst). Die meisten Typen erfüllen dies, außer Gleitkommazahlen (da NaN != NaN). Für Structs mit Integer-Feldern leiten Sie beide Traits zusammen ab:
#[derive(PartialEq, Eq)]
struct Coordinate {
x: i32,
y: i32,
}
Eq hat keine Methoden – es signalisiert reflexive Gleichheit. Einige Funktionen der Standardbibliothek erfordern Eq zusätzlich zu PartialEq.
Probier es selbst
mod color;
use color::Color;
fn main() {
// Lies die sechs RGB-Werte ein
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let r1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let g1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let b1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let r2: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let g2: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let b2: u8 = input.trim().parse().expect("Invalid input");
// TODO: Erstelle zwei Color-Instanzen unter Verwendung der parsierten Werte
// TODO: Gib Color 1 im Format: Color 1: rgb(r, g, b) aus
// TODO: Gib Color 2 im Format: Color 2: rgb(r, g, b) aus
// TODO: Vergleiche die beiden Farben mit == und gib aus: Colors match: {true/false}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Object Oriented Programming
1Methoden und Verhalten
Einführung in ImplementierungsblöckeDer Self-ParameterVeränderliche MethodenAssoziierte FunktionenMehrere ImplementierungsblöckeMethod ChainingRückblick – Rechteck-Aktionen4Projekt: Virtuelles Haustier
Das Haustier definierenDas Haustier füttern7Standard-Traits
Das Debug-TraitDas Display-TraitClone und CopyGleichheits-TraitsZusammenfassung – Druckbarer Punkt10Projekt: Dokumentensystem
Das Draw-TraitText-Komponente2Kapselung und Module
Grundlagen der ModuleDas Public-SchlüsselwortPrivate FelderGetterSetterWiederholung – Sicherer Tresor5Generics
Generische StructsGenerische MethodenMehrere generische TypenGenerische FunktionenZusammenfassung - Koordinatenpunkt8Traits als Einschränkungen
Syntax für Trait BoundsMehrfache BoundsDie Where-KlauselTypen mit Traits zurückgebenRückblick – Generischer Drucker11Design Patterns in Rust
Newtype-PatternKompositionDas Drop-TraitFrom und IntoZusammenfassung – Smart Pointer Mock3Fortgeschrittene Enums
Enums mit DatenMethoden für EnumsMatching von DatenvariantenDas Option-Enum erneut betrachtetZusammenfassung – Shape-Enum6Definition von Traits
Was ist ein Trait?Traits implementierenStandardimplementierungenStandardimplementierungen überschreibenTraits mit ParameternZusammenfassung – Media Player