Generics
Generische Identitätsfunktion
Abschnitt betitelt „Generische Identitätsfunktion“Stellen Sie sich vor, Sie verwenden eine Drittanbieterfunktion, deren Implementierung Sie nicht kennen, deren Typsignatur jedoch wie folgt aussieht:
fn mystery<T>(x: T) -> T { // ????}Dann rufen Sie mystery wie folgt auf:
let y = mystery(3);Angenommen, mystery verwendet keinen unsicheren Code, dann muss der Wert von y sein:
Die einzige mögliche Funktion (ohne unsicheren Code), die die Signatur T -> T hat, ist die Identitätsfunktion:
fn mystery<T>(x: T) -> T { x}Die Funktion könnte natürlich paniken oder etwas ausgeben, aber der Rückgabewert kann nur der Eingabewert sein. mystery weiß nicht, welchen Typ T hat, daher gibt es für mystery keine Möglichkeit, einen Wert vom Typ T zu generieren oder zu mutieren.
Weitere Beispiele für diese Idee finden Sie unter Theorems for free!.
Generische Typen drucken
Abschnitt betitelt „Generische Typen drucken“fn print_slice<T>(v: &[T]) { for x in v { println!("{x}"); }}
fn main() { print_slice(&[1, 2, 3]);}Wenn ein Typ generisch ist (wie T), können wir nichts über ihn annehmen, einschließlich der Fähigkeit, ihn in einen String umzuwandeln. Daher ist println!("{x}") ungültig, da x: &T ist.
Methoden-Kollision bei Impl
Abschnitt betitelt „Methoden-Kollision bei Impl“struct Point<T> { x: T, y: T }
impl Point<i32> { fn f(&self) -> &i32 { &self.y }}
impl<T> Point<T> { fn f(&self) -> &T { &self.x }}
fn main() { let p: Point<i32> = Point { x: 1, y: 2 }; println!("{}", p.f());}Diese Definitionen von f kollidieren, und Rust kann nicht bestimmen, welche f verwendet werden soll, wenn p.f() aufgerufen wird. Daher handelt es sich um einen Kompilierungsfehler.