Menu
Coddy logo textTech

Estructuras genéricas

Parte de la sección Programación Orientada a Objetos del Journey de Rust de Coddy. Lección 24 de 61.

Hasta ahora, todas las estructuras que has creado han tenido campos con tipos específicos y concretos. Un Pet tiene un nombre String, un Rectangle tiene dimensiones f64. Pero ¿qué ocurre si quieres crear una estructura que pueda contener cualquier tipo de datos?

Aquí es donde entran en juego los genéricos. Los genéricos te permiten escribir código flexible y reutilizable que funciona con múltiples tipos. En lugar de codificar directamente un tipo específico, utilizas un marcador de posición, normalmente T, que se reemplaza por un tipo concreto cuando utilizas la estructura.

Aquí tienes una estructura contenedora sencilla que puede contener cualquier tipo:

struct Wrapper<T> {
    value: T,
}

La <T> después del nombre de la estructura declara un parámetro de tipo genérico. Dentro de la estructura, T actúa como sustituto del tipo que realmente usarás. Cuando creas una instancia, Rust infiere el tipo concreto:

let int_wrapper = Wrapper { value: 42 };        // T es i32
let float_wrapper = Wrapper { value: 3.14 };    // T es f64
let text_wrapper = Wrapper { value: "hello" };  // T es &str

Cada uno de estos es un tipo concreto diferente, Wrapper<i32>, Wrapper<f64> y Wrapper<&str>, pero todos comparten la misma definición de estructura. Esto elimina la necesidad de escribir estructuras IntWrapper, FloatWrapper y StringWrapper separadas que esencialmente hacen lo mismo.

La letra T es solo una convención (abreviatura de «Tipo»). Podrías usar cualquier identificador válido, pero T es estándar en Rust y en la mayoría de los demás lenguajes con genéricos.

challenge icon

Desafío

Fácil

¡Construyamos un contenedor genérico que pueda contener cualquier tipo de valor! Crearás una estructura Container que demuestra cómo los genéricos hacen que tu código sea flexible y reutilizable.

Organizarás tu código en dos archivos:

  • container.rs: Define una estructura genérica pública llamada Container<T> con un único campo público item de tipo T. Este contenedor debe poder contener cualquier tipo: enteros, números de coma flotante, cadenas o cualquier otra cosa.
  • main.rs: Incluye tu módulo de contenedor y demuestra su flexibilidad creando contenedores que contienen diferentes tipos de datos. Crearás tres contenedores y mostrarás lo que contiene cada uno.

En tu archivo principal, crea los siguientes contenedores:

  1. Un contenedor que contenga un valor entero (la primera entrada, analizada como i32)
  2. Un contenedor que contenga un valor de coma flotante (la segunda entrada, analizada como f64)
  3. Un contenedor que contenga una cadena (la tercera entrada, conservada como String)

Tu salida debe mostrar el contenido de cada contenedor con este formato:

Integer container: {value}
Float container: {value}
String container: {value}

Por ejemplo, con las entradas 42, 3.14 y hello:

Integer container: 42
Float container: 3.14
String container: hello

Observa cómo la misma definición de Container<T> funciona para los tres tipos diferentes: ¡ese es el poder de los genéricos!

Recibirás tres entradas: un valor entero, un valor de coma flotante y un valor de cadena.

Pruébalo tú mismo

mod container;

use container::Container;

fn main() {
    // Lee las tres entradas
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let int_value: i32 = input1.trim().parse().expect("Failed to parse integer");

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let float_value: f64 = input2.trim().parse().expect("Failed to parse float");

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let string_value = input3.trim().to_string();

    // TODO: Create three containers using Container<T>
    // 1. An integer container holding int_value
    // 2. A float container holding float_value
    // 3. A string container holding string_value

    // TODO: Imprime el contenido de cada contenedor en el formato requerido
    // Integer container: {value}
    // Float container: {value}
    // String container: {value}
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Rust online