Menu
CoddyTech

Generische Funktionen

Teil des Abschnitts Objektorientierte Programmierung der Rust-Journey von Coddy. Lektion 27 von 61.

Generics sind nicht auf Structs beschränkt. Du kannst auch eigenständige Funktionen schreiben, die mit beliebigen Typen arbeiten. Das ist nützlich, wenn du eine Hilfsfunktion brauchst, die nicht zu einem bestimmten Struct gehört, aber trotzdem flexibel sein soll.

Die Syntax entspricht dem, was du bei Structs gesehen hast. Deklariere den generischen Parameter in spitzen Klammern nach dem Funktionsnamen und verwende ihn dann in den Parametern und im Rückgabetyp:

fn identity<T>(value: T) -> T {
    value
}

Diese Funktion identity nimmt einen Wert beliebigen Typs entgegen und gibt ihn unverändert zurück. <T> deklariert den generischen Typ, value: T nimmt ihn als Parameter entgegen, und -> T legt den Rückgabetyp fest. Wenn du die Funktion aufrufst, leitet Rust den konkreten Typ ab:

let num = identity(42);        // T ist i32
let text = identity("hello");  // T ist &str

Du kannst auch mehrere generische Parameter in Funktionen verwenden, genau wie bei Structs:

fn make_pair<T, U>(first: T, second: U) -> (T, U) {
    (first, second)
}

let pair = make_pair(10, "ten");  // gibt (i32, &str) zurück

Generische Funktionen ermöglichen es dir, wiederverwendbare Logik einmal zu schreiben und auf viele Typen anzuwenden. So reduzierst du doppelten Code und erhältst gleichzeitig die Typsicherheit.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Hilfsmodul mit generischen Funktionen, die mit jedem Typ arbeiten können! Du erstellst eigenständige Funktionen, die zeigen, wie Generics deinen Code flexibel und wiederverwendbar machen, ohne ihn an eine bestimmte Struktur zu binden.

Du organisierst deinen Code auf zwei Dateien:

  • utils.rs: Erstelle eine Sammlung öffentlicher generischer Hilfsfunktionen:
    • wrap_in_pair<T>: nimmt einen einzelnen Wert entgegen und gibt ein Tupel zurück, das diesen Wert zweimal enthält: (value, value). Dafür muss der Typ Clone implementieren, verwende also <T: Clone>
    • swap<T, U>: nimmt zwei Werte an, die unterschiedliche Typen haben können, und gibt sie in umgekehrter Reihenfolge als Tupel (U, T) zurück
  • main.rs: Binde dein Hilfsmodul ein und zeige, wie diese generischen Funktionen mit verschiedenen Typen funktionieren. Zeige, wie dieselben Funktionsdefinitionen nahtlos mit Ganzzahlen, Gleitkommazahlen und Zeichenfolgen umgehen.

Zeige in deiner Hauptdatei deine Hilfsfunktionen, indem du:

  1. wrap_in_pair mit einer Ganzzahl (erste Eingabe, als i32 geparst) verwendest und beide Elemente ausgibst
  2. wrap_in_pair mit einer Zeichenfolge (zweite Eingabe) verwendest und beide Elemente ausgibst
  3. swap mit einer Ganzzahl (dritte Eingabe, als i32 geparst) und einer Zeichenfolge (vierte Eingabe) verwendest und anschließend das vertauschte Ergebnis ausgibst

Deine Ausgabe sollte diesem Format entsprechen:

Pair of ints: ({value}, {value})
Pair of strings: ({value}, {value})
Swapped: ({string}, {int})

Zum Beispiel mit den Eingaben 5, hello, 42 und world:

Pair of ints: (5, 5)
Pair of strings: (hello, hello)
Swapped: (world, 42)

Beachte, wie wrap_in_pair bei Ganzzahlen und Zeichenfolgen identisch funktioniert und swap mit zwei völlig unterschiedlichen Typen umgehen kann: Das ist die Flexibilität generischer Funktionen!

Du erhältst vier Eingaben: eine Ganzzahl, eine Zeichenfolge, eine weitere Ganzzahl und eine weitere Zeichenfolge.

Probier es selbst

mod utils;

use std::io;

fn main() {
    // Lies die vier Eingaben ein
    let mut input1 = String::new();
    io::stdin().read_line(&mut input1).expect("Failed to read line");
    let num1: i32 = input1.trim().parse().expect("Invalid integer");

    let mut input2 = String::new();
    io::stdin().read_line(&mut input2).expect("Failed to read line");
    let str1 = input2.trim().to_string();

    let mut input3 = String::new();
    io::stdin().read_line(&mut input3).expect("Failed to read line");
    let num2: i32 = input3.trim().parse().expect("Invalid integer");

    let mut input4 = String::new();
    io::stdin().read_line(&mut input4).expect("Failed to read line");
    let str2 = input4.trim().to_string();

    // TODO: Verwende wrap_in_pair mit num1 und gib das Ergebnis aus
    // Format: Pair of ints: ({value}, {value})

    // TODO: Verwende wrap_in_pair mit str1 und gib das Ergebnis aus
    // Format: Pair of strings: ({value}, {value})

    // TODO: Verwende swap mit num2 und str2 und gib anschließend das vertauschte Ergebnis aus
    // Format: Swapped: ({string}, {int})
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-Rust-Compiler