Menu
Coddy logo textTech

Métodos en Enums

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

Al igual que los structs, los enums pueden tener métodos definidos en bloques impl. Esto te permite adjuntar comportamiento directamente a tu tipo enum, facilitando el trabajo con diferentes variantes a través de una interfaz unificada.

Aquí se explica cómo añadir un método al enum Message de la lección anterior:

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

impl Message {
    fn describe(&self) -> String {
        match self {
            Message::Quit => String::from("Quit signal"),
            Message::Move { x, y } => format!("Move to ({}, {})", x, y),
            Message::Write(text) => format!("Message: {}", text),
        }
    }
}

El bloque impl Message funciona exactamente igual que para las estructuras. El método toma &self para acceder a la instancia del enum. Dentro del método, usas match para determinar con qué variante estás tratando y devolver el resultado apropiado.

Llamar al método se ve igual independientemente de qué variante tengas:

fn main() {
    let m1 = Message::Quit;
    let m2 = Message::Move { x: 10, y: 20 };
    
    println!("{}", m1.describe());  // Señal de salida
    println!("{}", m2.describe());  // Mover a (10, 20)
}

Este patrón es potente porque el llamador no necesita saber qué variante tiene; simplemente llama al método y el enum se encarga del resto internamente. El comportamiento cambia según la variante, pero la interfaz se mantiene consistente.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de semáforo que utiliza un enum con métodos para describir el estado actual de la señal. Cada color de luz llevará información sobre cuánto tiempo dura, y un método proporcionará una descripción legible para los humanos.

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

  • traffic.rs: Define un enum público TrafficLight con tres variantes:
    • Red — contiene un u32 que representa los segundos de espera
    • Yellow — contiene un u32 que representa los segundos de espera
    • Green — contiene un u32 que representa los segundos para avanzar
    Luego, implementa un método status que devuelva un String describiendo la luz. Usa match dentro del método para manejar cada variante e incluir la duración en el mensaje.
  • main.rs: Importa tu módulo de tráfico, crea instancias de cada variante de luz y llama al método status en cada una para imprimir las descripciones.

El método status debe devolver mensajes en estos formatos exactos:

  • Para Red: Stop for {seconds} seconds
  • Para Yellow: Caution for {seconds} seconds
  • Para Green: Go for {seconds} seconds

Tu salida debe mostrar el estado de cada luz en su propia línea:

Stop for {seconds} seconds
Caution for {seconds} seconds
Go for {seconds} seconds

Por ejemplo, con una luz roja de 30 segundos, amarilla de 5 segundos y verde de 25 segundos, la salida sería:

Stop for 30 seconds
Caution for 5 seconds
Go for 25 seconds

Recibirás tres entradas: la duración de la luz roja, la duración de la luz amarilla y la duración de la luz verde.

Hoja de referencia

Los enums pueden tener métodos definidos en bloques impl, al igual que los structs:

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

impl Message {
    fn describe(&self) -> String {
        match self {
            Message::Quit => String::from("Quit signal"),
            Message::Move { x, y } => format!("Move to ({}, {})", x, y),
            Message::Write(text) => format!("Message: {}", text),
        }
    }
}

Los métodos toman &self para acceder a la instancia del enum y usan match para manejar las diferentes variantes:

let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };

println!("{}", m1.describe());  // Señal de salida
println!("{}", m2.describe());  // Mover a (10, 20)

El llamador utiliza la misma interfaz independientemente de la variante; el enum maneja el comportamiento internamente basándose en qué variante es.

Pruébalo tú mismo

mod traffic;

use traffic::TrafficLight;

fn main() {
    // Lee la entrada para las duraciones
    let mut red_input = String::new();
    std::io::stdin().read_line(&mut red_input).expect("Failed to read line");
    let red_duration: u32 = red_input.trim().parse().expect("Invalid number");

    let mut yellow_input = String::new();
    std::io::stdin().read_line(&mut yellow_input).expect("Failed to read line");
    let yellow_duration: u32 = yellow_input.trim().parse().expect("Invalid number");

    let mut green_input = String::new();
    std::io::stdin().read_line(&mut green_input).expect("Failed to read line");
    let green_duration: u32 = green_input.trim().parse().expect("Invalid number");

    // TODO: Crea instancias de cada variante de TrafficLight con las duraciones de entrada

    // TODO: Llama al método status en cada luz e imprime el resultado
}
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