Rust soporta genéricos, lo que le permite abstraer algoritmos o estructuras de datos (como ordenamiento o un árbol binario) sobre los tipos definidos por nosotros o por el sdk.
Puede utilizar genéricos para abstraer el tipo de campo concreto:
#[derive(Debug)]
struct Point<T> {
x: T,
y: T,
}
fn main() {
let integer = Point { x: 5, y: 10 };
let float = Point { x: 1.0, y: 4.0 };
println!("{integer:?} and {float:?}");
}
Lo hermoso es que infiere el tipo dependiendo de como lo usamos. Es decir, si hacemos :
let x = Point { x: 5, y: 10.0 };
no va a compilar.
Se puedes declarar un tipo genérico en tu bloque impl:
#[derive(Debug)]
struct Point<T>(T, T);
impl<T> Point<T> {
fn x(&self) -> &T {
&self.0 // + 10
}
// fn set_x(&mut self, x: T)
}
fn main() {
let p = Point(5, 10);
println!("p.x = {}", p.x());
}
¿Por qué T se especifica dos veces en impl<T> Point<T> {}? ¿No es eso redundante?
Esto se debe a que es una sección de implementación genérica para tipos genéricos. Son genéricos independientemente. Significa que estos métodos están definidos para cualquier T.
Es posible escribir impl Point<u32> { .. }.
Point sigue siendo genérico y puedes usar Point<f64>, pero los métodos de este bloque solo estarán disponibles para Point<u32>.