Menu
Coddy logo textTech

Enums con datos

Parte de la sección Object Oriented Programming del Journey de Rust de Coddy — lección 14 de 61.

Los enums básicos en Rust te permiten definir un tipo con un conjunto fijo de variantes—como Direction::North o Status::Active. Pero los enums de Rust son mucho más potentes que eso. Cada variante puede contener sus propios datos, lo que hace que los enums sean increíblemente flexibles para modelar escenarios del mundo real.

Considera un sistema de mensajería donde diferentes tipos de mensajes llevan información diferente. Un mensaje de texto tiene contenido, un comando de movimiento tiene coordenadas y una señal de salida no tiene nada en absoluto. En Rust, puedes representar todo esto con un solo enum:

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(u8, u8, u8),
}

Cada variante tiene una forma diferente. Quit no contiene datos; es solo una señal.

Move utiliza una sintaxis similar a una estructura con campos con nombre. Write contiene una única String utilizando sintaxis de tupla. ChangeColor contiene tres valores que representan componentes RGB.

La creación de instancias de estas variantes se ve así:

let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
let m3 = Message::Write(String::from("Hello"));
let m4 = Message::ChangeColor(255, 128, 0);

La belleza de este enfoque es que m1, m2, m3 y m4 son todos del mismo tipo: Message. Puedes almacenarlos en la misma colección, pasarlos a la misma función o devolver cualquier variante desde una sola función. El enum unifica diferentes formas de datos bajo un solo tipo mientras preserva la información específica que cada variante necesita.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de notificaciones que utiliza enums con datos para representar diferentes tipos de alertas. Cada tipo de notificación lleva información diferente: algunas tienen mensajes, otras tienen valores numéricos y otras son simples señales.

Crearás dos archivos para organizar tu código:

  • notification.rs: Define un enum Notification público con tres variantes:
    • Alert — contiene un único mensaje String (sintaxis de tupla)
    • Reminder — contiene campos con nombre: title (String) y minutes (u32)
    • Dismiss — no contiene datos, es solo una señal
  • main.rs: Importa tu módulo de notificación y crea una instancia de cada variante. Luego, imprime la información de cada notificación para demostrar que las tres variantes son del mismo tipo pero contienen datos diferentes.

Al imprimir, utiliza el formateo de depuración ({:?}) para mostrar cada notificación. Necesitarás derivar el trait Debug en tu enum para que pueda imprimirse de esta manera.

Tu salida debería mostrar las tres notificaciones, cada una en su propia línea:

Alert("{message}")
Reminder { title: "{title}", minutes: {minutes} }
Dismiss

Por ejemplo, con un mensaje de alerta de "Server down", un recordatorio con el título "Meeting" y 30 minutos, la salida sería:

Alert("Server down")
Reminder { title: "Meeting", minutes: 30 }
Dismiss

Recibirás tres entradas: el mensaje de alerta, el título del recordatorio y los minutos del recordatorio.

Hoja de referencia

Las variantes de los enums en Rust pueden contener diferentes tipos de datos, lo que las hace potentes para modelar diversos escenarios bajo un solo tipo.

Definición de enums con datos

Cada variante puede tener su propia estructura de datos:

enum Message {
    Quit,                          // Sin datos
    Move { x: i32, y: i32 },      // Campos con nombre (tipo struct)
    Write(String),                 // Valor único (sintaxis de tupla)
    ChangeColor(u8, u8, u8),      // Múltiples valores (sintaxis de tupla)
}

Creación de instancias de enums

let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
let m3 = Message::Write(String::from("Hello"));
let m4 = Message::ChangeColor(255, 128, 0);

Todas las instancias son del mismo tipo (Message) a pesar de contener datos diferentes, lo que permite almacenarlas en colecciones, pasarlas a funciones o devolverlas desde funciones de manera uniforme.

Trait Debug

Para imprimir enums usando el formato {:?}, derive el trait Debug:

#[derive(Debug)]
enum Message {
    // variantes...
}

Pruébalo tú mismo

mod notification;

use notification::Notification;

fn main() {
    // Leer entradas
    let mut alert_message = String::new();
    std::io::stdin().read_line(&mut alert_message).expect("Failed to read line");
    let alert_message = alert_message.trim().to_string();

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

    let mut minutes_input = String::new();
    std::io::stdin().read_line(&mut minutes_input).expect("Failed to read line");
    let reminder_minutes: u32 = minutes_input.trim().parse().expect("Failed to parse minutes");

    // TODO: Crear una notificación de tipo Alert usando alert_message

    // TODO: Crear una notificación de tipo Reminder usando reminder_title y reminder_minutes

    // TODO: Crear una notificación de tipo Dismiss

    // TODO: Imprimir cada notificación usando el formato de depuración {:?}
    // Cada notificación debe imprimirse en su propia línea
}
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 Object Oriented Programming