Menu
Coddy logo textTech

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 jedem Typ funktionieren. Das ist nützlich, wenn du eine Hilfsfunktion benötigst, die nicht zu einem bestimmten struct gehört, aber dennoch flexibel sein sollte.

Die Syntax entspricht dem, was du bereits bei Strukturen 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 eines beliebigen Typs entgegen und gibt ihn unverändert zurück. <T> deklariert den generischen Typ, value: T akzeptiert ihn als Parameter, 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 in Funktionen auch mehrere generische Parameter verwenden, genau wie bei Strukturen:

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. Dadurch wird doppelter Code reduziert und gleichzeitig die Typsicherheit beibehalten.

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 über 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 potenziell unterschiedlicher Typen entgegen und gibt sie in umgekehrter Reihenfolge als Tupel (U, T) zurück
  • main.rs: Importiere dein Hilfsmodul und demonstriere diese generischen Funktionen mit verschiedenen Typen. Zeige, wie dieselben Funktionsdefinitionen nahtlos Ganzzahlen, Gleitkommazahlen und Zeichenketten verarbeiten.

Demonstriere 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 Zeichenkette (zweite Eingabe) verwendest und beide Elemente ausgibst
  3. swap mit einer Ganzzahl (dritte Eingabe, als i32 geparst) und einer Zeichenkette (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 für Ganzzahlen und Zeichenketten identisch funktioniert und swap zwei völlig unterschiedliche Typen verarbeitet: Das ist die Flexibilität generischer Funktionen!

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

Probier es selbst

mod utils;

use std::io;

fn main() {
    // Lese die vier Eingaben
    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, dann gib 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