Menu
Coddy logo textTech

Enums com Dados

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

Enums básicos em Rust permitem que você defina um tipo com um conjunto fixo de variantes—como Direction::North ou Status::Active. Mas os enums de Rust são muito mais poderosos do que isso. Cada variante pode carregar seus próprios dados, tornando os enums incrivelmente flexíveis para modelar cenários do mundo real.

Considere um sistema de mensagens onde diferentes tipos de mensagens carregam informações diferentes. Uma mensagem de texto possui conteúdo, um comando de movimento possui coordenadas e um sinal de saída não possui nada. Em Rust, você pode representar tudo isso com um único enum:

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

Cada variante possui uma forma diferente. Quit não contém dados — é apenas um sinal.

Move usa sintaxe semelhante a struct com campos nomeados. Write contém uma única String usando sintaxe de tupla. ChangeColor contém três valores representando componentes RGB.

A criação de instâncias dessas variantes é feita desta forma:

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);

A beleza desta abordagem é que m1, m2, m3 e m4 são todos do mesmo tipo: Message. Você pode armazená-los na mesma coleção, passá-los para a mesma função ou retornar qualquer variante de uma única função. O enum unifica diferentes formatos de dados sob um único tipo, enquanto preserva a informação específica que cada variante necessita.

challenge icon

Desafio

Fácil

Vamos construir um sistema de notificação que utiliza enums com dados para representar diferentes tipos de alertas. Cada tipo de notificação carrega informações diferentes — algumas possuem mensagens, algumas possuem valores numéricos e outras são simples sinais.

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

  • notification.rs: Defina um enum público Notification com três variantes:
    • Alert — contém uma única mensagem String (sintaxe de tupla)
    • Reminder — contém campos nomeados: title (String) e minutes (u32)
    • Dismiss — não contém dados, apenas um sinal
  • main.rs: Importe seu módulo de notificação e crie uma instância de cada variante. Em seguida, imprima as informações sobre cada notificação para demonstrar que todas as três variantes são do mesmo tipo, mas carregam dados diferentes.

Ao imprimir, use a formatação de debug ({:?}) para exibir cada notificação. Você precisará derivar a trait Debug em seu enum para que ele possa ser impresso dessa forma.

Sua saída deve mostrar todas as três notificações, cada uma em sua própria linha:

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

Por exemplo, com uma mensagem de alerta "Server down", um lembrete com o título "Meeting" e 30 minutos, a saída seria:

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

Você receberá três entradas: a mensagem de alerta, o título do lembrete e os minutos do lembrete.

Folha de consulta

As variantes de enum em Rust podem carregar diferentes tipos de dados, tornando-as poderosas para modelar diversos cenários sob um único tipo.

Definindo Enums com Dados

Cada variante pode ter sua própria estrutura de dados:

enum Message {
    Quit,                          // No data
    Move { x: i32, y: i32 },      // Named fields (struct-like)
    Write(String),                 // Single value (tuple syntax)
    ChangeColor(u8, u8, u8),      // Multiple values (tuple syntax)
}

Criando Instâncias de Enum

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 as instâncias são do mesmo tipo (Message), apesar de carregarem dados diferentes, permitindo que sejam armazenadas em coleções, passadas para funções ou retornadas de funções de forma uniforme.

Trait Debug

Para imprimir enums usando a formatação {:?}, derive a trait Debug:

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

Experimente você mesmo

mod notification;

use notification::Notification;

fn main() {
    // Ler 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: Criar uma notificação Alert usando alert_message

    // TODO: Criar uma notificação Reminder usando reminder_title e reminder_minutes

    // TODO: Criar uma notificação Dismiss

    // TODO: Imprimir cada notificação usando formatação de debug {:?}
    // Cada notificação deve ser impressa em sua própria linha
}
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