Los genéricos en Rust permiten escribir código flexible y reutilizable. En lugar de definir funciones, structs o enums para cada tipo de dato específico, puedes usar genéricos para trabajar con cualquier tipo de dato. Este enfoque no solo reduce la duplicación de código, sino que también mejora la legibilidad y el mantenimiento del código.
Conceptos Clave
- Definición de Genéricos: Los genéricos se definen utilizando el símbolo
<T>
, dondeT
es un marcador de posición para un tipo de dato. - Funciones Genéricas: Permiten que las funciones trabajen con diferentes tipos de datos sin necesidad de definir múltiples versiones de la misma función.
- Structs Genéricos: Permiten que las estructuras almacenen diferentes tipos de datos.
- Enums Genéricos: Permiten que los enums manejen diferentes tipos de datos en sus variantes.
Funciones Genéricas
Ejemplo Básico
fn largest<T: PartialOrd>(list: &[T]) -> &T { let mut largest = &list[0]; for item in list { if item > largest { largest = item; } } largest }
Explicación
fn largest<T: PartialOrd>(list: &[T]) -> &T
: Define una función genéricalargest
que acepta una referencia a un slice de cualquier tipoT
que implemente el traitPartialOrd
(necesario para comparar elementos).let mut largest = &list[0];
: Inicializalargest
con la referencia al primer elemento del slice.for item in list
: Itera sobre cada elemento en el slice.if item > largest
: Compara el elemento actual con el más grande encontrado hasta ahora.largest = item;
: Actualizalargest
si se encuentra un elemento mayor.
Ejercicio
Escribe una función genérica smallest
que encuentre el elemento más pequeño en un slice.
Solución
fn smallest<T: PartialOrd>(list: &[T]) -> &T { let mut smallest = &list[0]; for item in list { if item < smallest { smallest = item; } } smallest }
Structs Genéricos
Ejemplo Básico
Explicación
struct Point<T>
: Define una estructura genéricaPoint
con dos camposx
yy
del mismo tipoT
.impl<T> Point<T>
: Implementa métodos para la estructuraPoint
.fn new(x: T, y: T) -> Self
: Método constructor que crea una nueva instancia dePoint
.
Ejercicio
Define una estructura genérica Rectangle
con campos width
y height
, y un método area
que calcule el área del rectángulo.
struct Rectangle<T> { width: T, height: T, } impl<T> Rectangle<T> { fn area(&self) -> T { // Tu código aquí } }
Solución
struct Rectangle<T> { width: T, height: T, } impl<T: std::ops::Mul<Output = T> + Copy> Rectangle<T> { fn area(&self) -> T { self.width * self.height } }
Enums Genéricos
Ejemplo Básico
Explicación
enum Option<T>
: Define un enum genéricoOption
con dos variantes:Some
que contiene un valor de tipoT
yNone
que no contiene ningún valor.
Ejercicio
Define un enum genérico Result
con dos variantes: Ok
que contiene un valor de tipo T
y Err
que contiene un valor de tipo E
.
Solución
Conclusión
Los genéricos en Rust son una herramienta poderosa que permite escribir código más flexible y reutilizable. Al entender cómo definir y utilizar funciones, structs y enums genéricos, puedes crear programas más eficientes y fáciles de mantener. En el siguiente módulo, exploraremos la concurrencia en Rust, que te permitirá escribir programas que aprovechen al máximo los procesadores multinúcleo.
Curso de Programación en Rust
Módulo 1: Introducción a Rust
- ¿Qué es Rust?
- Configuración del Entorno de Rust
- Programa "Hola, Mundo!"
- Sintaxis y Estructura Básica