Menu
Coddy logo textTech

Métodos em Enums

Parte da seção Object Oriented Programming do Journey de Rust da Coddy — lição 15 de 61.

Assim como as structs, enums podem ter métodos definidos em blocos impl. Isso permite que você anexe comportamento diretamente ao seu tipo enum, tornando fácil trabalhar com diferentes variantes através de uma interface unificada.

Veja como adicionar um método ao enum Message da lição 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),
        }
    }
}

O bloco impl Message funciona exatamente como para structs. O método recebe &self para acessar a instância do enum. Dentro do método, você usa match para determinar com qual variante está lidando e retornar o resultado apropriado.

Chamar o método parece o mesmo, independentemente de qual variante você tenha:

fn main() {
    let m1 = Message::Quit;
    let m2 = Message::Move { x: 10, y: 20 };
    
    println!("{}", m1.describe());  // Sinal de encerramento
    println!("{}", m2.describe());  // Mover para (10, 20)
}

Este padrão é poderoso porque o chamador não precisa saber qual variante possui — ele apenas chama o método, e o enum lida com o restante internamente. O comportamento muda com base na variante, mas a interface permanece consistente.

challenge icon

Desafio

Fácil

Vamos construir um sistema de semáforo que utiliza um enum com métodos para descrever o estado atual do sinal. Cada cor da luz carregará informações sobre quanto tempo ela dura, e um método fornecerá uma descrição legível por humanos.

Você criará dois arquivos para organizar seu código:

  • traffic.rs: Defina um enum público TrafficLight com três variantes:
    • Red — contém um u32 representando os segundos de espera
    • Yellow — contém um u32 representando os segundos de espera
    • Green — contém um u32 representando os segundos para seguir
    Em seguida, implemente um método status que retorna uma String descrevendo a luz. Use match dentro do método para lidar com cada variante e inclua a duração na mensagem.
  • main.rs: Importe seu módulo traffic, crie instâncias de cada variante de luz e chame o método status em cada uma para imprimir as descrições.

O método status deve retornar mensagens nestes formatos exatos:

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

Sua saída deve exibir o status de cada luz em sua própria linha:

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

Por exemplo, com uma luz vermelha de 30 segundos, amarela de 5 segundos e verde de 25 segundos, a saída seria:

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

Você receberá três entradas: a duração da luz vermelha, a duração da luz amarela e a duração da luz verde.

Folha de consulta

Enums podem ter métodos definidos em blocos impl, assim como as 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),
        }
    }
}

Os métodos recebem &self para acessar a instância da enum e usam match para lidar com as diferentes variantes:

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

println!("{}", m1.describe());  // Quit signal
println!("{}", m2.describe());  // Move to (10, 20)

O chamador usa a mesma interface independentemente da variante — a enum lida com o comportamento internamente com base em qual variante ela é.

Experimente você mesmo

mod traffic;

use traffic::TrafficLight;

fn main() {
    // Lê a entrada para as durações
    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: Criar instâncias de cada variante de TrafficLight com as durações de entrada

    // TODO: Chamar o método status em cada semáforo e imprimir o resultado
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Object Oriented Programming