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 tem conteúdo, um comando de movimento tem coordenadas e um sinal de saída não tem 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 tem 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 destas 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 dessa 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, preservando as informações específicas que cada variante necessita.
Desafio
FácilVamos 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 — alguns possuem mensagens, alguns possuem valores numéricos e outros são simples sinais.
Você criará dois arquivos para organizar seu código:
notification.rs: Defina um enum públicoNotificationcom três variantes:Alert— contém uma única mensagemString(sintaxe de tupla)Reminder— contém campos nomeados:title(String) eminutes(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 depuração ({:?}) 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} }
DismissPor 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 }
DismissVocê receberá três entradas: a mensagem de alerta, o título do lembrete e os minutos do lembrete.
Experimente você mesmo
mod notification;
use notification::Notification;
fn main() {
// Ler as 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 o 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 a formatação de debug {:?}
// Cada notificação deve ser impressa em sua própria linha
}
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
1Métodos e Comportamento
Introdução a Blocos de ImplementaçãoO Parâmetro SelfMétodos MutáveisFunções AssociadasMúltiplos Blocos de ImplementaçãoEncadeamento de MétodosRecapitulação - Ações de Retângulo4Projeto: Pet Virtual
Definindo o PetAlimentando o Pet7Traits Padrão
A Trait DebugA Trait DisplayClone e CopyTraits de IgualdadeRecapitulação - Ponto Imprimível10Projeto: Sistema de Documentos
A Trait DrawComponente de Texto2Encapsulamento e Módulos
Fundamentos de MódulosA Palavra-chave PublicCampos PrivadosGettersSettersRecapitulação - Cofre Seguro5Genéricos
Structs GenéricasMétodos GenéricosMúltiplos Tipos GenéricosFunções GenéricasRecapitulação - Ponto de Coordenada8Traits como Restrições
Sintaxe de Restrições de TraitRestrições MúltiplasA Cláusula WhereRetornando Tipos com TraitsRecapitulação - Impressora Genérica11Padrões de Projeto em Rust
Padrão NewtypeComposiçãoA Trait DropFrom e IntoRecapitulação - Mock de Smart Pointer3Enums Avançados
Enums com DadosMétodos em EnumsCorrespondência de Variantes de DadosO Enum Option RevisitadoRecapitulação - Enum Shape6Definição de Traits
O que é uma Trait?Implementando TraitsImplementações PadrãoSobrescrevendo PadrõesTraits com ParâmetrosRecapitulação - Media Player