Traits implementieren
Teil des Abschnitts Objektorientierte Programmierung der Rust-Journey von Coddy. Lektion 30 von 61.
Da du nun weißt, wie man ein Trait definiert, sehen wir uns an, wie man eine Struct diesen Vertrag erfüllen lässt. Die Implementierung eines Traits verbindet die abstrakte Anforderung mit konkretem Verhalten.
Die Syntax verwendet impl TraitName for StructName:
trait Speak {
fn speak(&self) -> String;
}
struct Dog {
name: String,
}
impl Speak for Dog {
fn speak(&self) -> String {
format!("{} says: Woof!", self.name)
}
}
Der Block impl Speak for Dog teilt Rust mit, dass Dog das Speak-Trait implementiert. Darin stellst du den eigentlichen Methodenrumpf bereit. Hier definierst du, wie ein Hund spricht.
Die Leistungsfähigkeit von Traits wird deutlich, wenn mehrere Typen dasselbe Trait implementieren:
struct Cat {
name: String,
}
impl Speak for Cat {
fn speak(&self) -> String {
format!("{} says: Meow!", self.name)
}
}
Dog und Cat verfügen nun beide über die Fähigkeit Speak, aber jeder Typ bietet seine eigene Implementierung. Du kannst .speak() für jeden der beiden Typen aufrufen:
let dog = Dog { name: String::from("Rex") };
let cat = Cat { name: String::from("Whiskers") };
println!("{}", dog.speak()); // Rex sagt: Wuff!
println!("{}", cat.speak()); // Whiskers sagt: Miau!
Dies ist die Grundlage des Polymorphismus in Rust: verschiedene Typen, dieselbe Schnittstelle, einzigartige Verhaltensweisen.
Aufgabe
EinfachErwecke Traits zum Leben, indem du sie für verschiedene Typen implementierst! Du erstellst einen Describable-Trait und implementierst ihn für zwei verschiedene Structs, wobei jedes seine eigene eindeutige Beschreibung liefert.
Du organisierst deinen Code über drei Dateien:
describable.rs: Definiere einen öffentlichenDescribable-Trait mit einer Methodedescribe(&self) -> String.items.rs: Erstelle zwei öffentliche Structs, die deinen Trait implementieren:Bookmit einem öffentlichentitle-Feld (String)Moviemit einem öffentlichenname-Feld (String)
Describablemit seinem eigenen eindeutigen Beschreibungsformat implementieren.main.rs: Führe deine Module zusammen, erstelle Instanzen beider Structs und rufe ihredescribe-Methoden auf, um zu zeigen, wie derselbe Trait für verschiedene Typen unterschiedliche Ausgaben erzeugt.
Dein Book sollte sich als Book: {title} beschreiben, und dein Movie sollte sich als Film: {name} beschreiben. Beachte, wie jeder Typ denselben Vertrag erfüllt, sich aber auf seine eigene Weise verhält!
Erstelle in deiner Hauptdatei ein Buch und einen Film mithilfe der beiden bereitgestellten Eingaben und gib ihre Beschreibungen in separaten Zeilen aus.
Deine Ausgabe sollte diesem Format entsprechen:
Book: {title}
Film: {name}Zum Beispiel mit den Eingaben 1984 und Inception:
Book: 1984
Film: InceptionDu erhältst zwei Eingaben: einen Buchtitel und einen Filmnamen.
Probier es selbst
mod describable;
mod items;
use describable::Describable;
use items::{Book, Movie};
fn main() {
// Eingaben lesen
let mut title = String::new();
std::io::stdin().read_line(&mut title).expect("Failed to read line");
let title = title.trim().to_string();
let mut name = String::new();
std::io::stdin().read_line(&mut name).expect("Failed to read line");
let name = name.trim().to_string();
// TODO: Erstelle eine Book-Instanz mit dem title
// TODO: Erstelle eine Movie-Instanz mit dem name
// TODO: Gib die Beschreibung des Buchs aus
// TODO: Gib die Beschreibung des Films aus
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
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Übe selbstständig: Online-Rust-Compiler