Lektionen des Moduls (1/2)
Generics und Funktionen
Generics (generische Typen) ermöglichen es Ihnen, flexiblen und wiederverwendbaren Code zu schreiben und die Duplizierung von Logik für verschiedene Datentypen zu vermeiden. Anstatt mehrere Funktionen oder Strukturen für verschiedene Typen (wie i32, f64 oder String) zu definieren, können wir einen generischen Typparameter verwenden, der konventionell mit dem Buchstaben T bezeichnet wird.
Der Rust-Compiler verarbeitet Generics durch einen Prozess namens Monomorphisierung: Während der Kompilierung generiert der Compiler eine Kopie des generischen Codes für jeden konkreten Typ, mit dem er tatsächlich verwendet wird. Auf diese Weise entsteht zur Laufzeit kein Leistungs-Overhead.
Generische Funktionen
Um eine generische Funktion zu definieren, setzen wir den Typparameter <T> direkt nach dem Funktionsnamen und vor der Parameterliste ein:
fn print_value<T: std::fmt::Debug>(value: T) {
println!("Valore: {:?}", value);
}
In generischen Funktionen können wir den generischen Typ T sowohl für die Argumenttypen als auch für den Rückgabetyp verwenden:
fn identity<T>(value: T) -> T {
value
}
Generische Strukturen
Wir können generische Typparameter auch innerhalb von Datenstrukturen (struct) verwenden, um flexible Felder zu definieren:
struct KeyValuePair<K, V> {
key: K,
value: V,
}
fn main() {
let pair = KeyValuePair {
key: String::from("eta"),
value: 30,
};
}
Im impl-Block für eine generische Struct müssen wir den Typparameter <T> direkt nach dem Schlüsselwort impl deklarieren, um anzuzeigen, dass wir Methoden für eine generische Struktur implementieren:
struct Container<T> {
value: T,
}
impl<T> Container<T> {
fn new(value: T) -> Self {
Container { value }
}
fn value(&self) -> &T {
&self.value
}
}
Probiere es aus
Übung 1: Die Struktur Point
Definieren Sie eine generische Struktur namens Point<T> mit zwei Feldern: x vom Typ T und y vom Typ T. Instanziieren Sie in der main-Methode eine Variable point, die einen Point mit den Werten x gleich 5 und y gleich 10 (Ganzzahlen) enthält, und geben Sie dann den Wert von point.x aus.
Hinweis anzeigen
Deklarieren Sie die Struct mit `struct Point<T> { x: T, y: T }`. Instanziieren Sie sie in main und verwenden Sie `point.x`, um sie auszugeben.
Lösung nach 3 Versuchen verfügbar
Übung 2: Vertauschen eines Tupels mit swap
Schreiben Sie eine generische Funktion namens swap<T>, die ein Tupel aus zwei Elementen (T, T) als Parameter akzeptiert und ein neues Tupel (T, T) zurückgibt, bei dem die Positionen der Elemente vertauscht sind. Rufen Sie die Funktion in main mit dem Tupel (1, 2) auf und geben Sie das Ergebnis aus.
Hinweis anzeigen
Die Signatur der Funktion muss `fn swap<T>(pair: (T, T)) -> (T, T)`sein. Geben Sie das vertauschte Tupel mit`(pair.1, pair.0)` zurück.
Lösung nach 3 Versuchen verfügbar
Übung 3: Die Struktur Container
Definieren Sie eine generische Struct Container<T>, die ein Feld value vom Typ T enthält. Implementieren Sie einen generischen impl-Block, um eine Methode new zu definieren, die einen Wert vom Typ T akzeptiert und eine Instanz von Container<T> zurückgibt.
Hinweis anzeigen
Verwenden Sie `impl<T> Container<T>`, um die assoziierte Methode `fn new(value: T) -> Self { Container { value } }` zu implementieren.
Lösung nach 3 Versuchen verfügbar