Translate

jueves, 5 de octubre de 2023

Generics en Rust


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>.