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.
Desafio
FácilVamos 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úblicoTrafficLightcom três variantes:Red— contém umu32representando os segundos de esperaYellow— contém umu32representando os segundos de esperaGreen— contém umu32representando os segundos para seguir
statusque retorna umaStringdescrevendo a luz. Usematchdentro 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étodostatusem 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} secondsPor 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 secondsVocê 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
}
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