Direkt zum Hauptinhalt springen
eLearner.app
Modul 5 · Lektion 1 von 29/14 im Kurs~12 min
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:

Code
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:

Code
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:

Code
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:

Code
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

Übung#rust.m5.l1.e1
Versuche: 0Wird geladen…

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.

Editor wird geladen…
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

Übung#rust.m5.l1.e2
Versuche: 0Wird geladen…

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.

Editor wird geladen…
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

Übung#rust.m5.l1.e3
Versuche: 0Wird geladen…

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.

Editor wird geladen…
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