Correspondência de Variantes de Dados
Parte da seção Programação Orientada a Objetos do Journey de Rust da Coddy. Lição 16 de 61.
Na lição anterior, você usou match dentro de métodos de enum para lidar com diferentes variantes. Agora vamos nos concentrar em como match realmente extrai os dados armazenados nessas variantes: uma técnica chamada desestruturação.
Quando você usa match em uma variante de enum que contém dados, pode vincular esses dados a variáveis diretamente no padrão:
enum Event {
Click { x: i32, y: i32 },
KeyPress(char),
Resize(u32, u32),
}
fn handle_event(event: Event) {
match event {
Event::Click { x, y } => {
println!("Clicked at ({}, {})", x, y);
}
Event::KeyPress(key) => {
println!("Key pressed: {}", key);
}
Event::Resize(width, height) => {
println!("Resized to {}x{}", width, height);
}
}
}
Cada braço extrai dados de forma diferente com base na estrutura da variante. Para variantes semelhantes a structs, você usa { field_name } para extrair campos nomeados. Para variantes de tupla, você usa variáveis posicionais como (width, height).
Os nomes de variáveis que você escolher ficam disponíveis dentro desse braço de match. Isso é poderoso porque você verifica simultaneamente qual variante possui e obtém acesso aos dados associados a ela.
O compilador garante que você trate todas as variantes, e os valores extraídos estão prontos para uso imediato: nenhuma etapa extra é necessária.
Desafio
FácilVamos criar um processador de comandos que lide com diferentes tipos de comandos do usuário. Cada comando contém dados diferentes, e seu processador usará correspondência de padrões para extrair esses dados e produzir respostas apropriadas.
Você criará dois arquivos para organizar seu código:
command.rs: defina um enum públicoCommandcom três variantes:Say: contém uma única mensagemString(sintaxe de tupla)Move: contém campos nomeados:direction(String) esteps(u32)Calculate: contém dois valoresi32representando números a serem somados (sintaxe de tupla)
executeque usematchpara desestruturar cada variante e retorne umaStringdescrevendo a ação realizada.main.rs: inclua seu módulo de comandos, crie uma instância de cada variante de comando usando as entradas fornecidas e chame o métodoexecuteem cada uma para imprimir os resultados.
Seu método execute deve desestruturar cada variante para acessar seus dados e retornar mensagens nestes formatos exatos:
- Para
Say:Saying: {message} - Para
Move:Moving {steps} steps {direction} - Para
Calculate:{a} + {b} = {sum}
Sua saída deve exibir o resultado de cada comando em sua própria linha:
Saying: {message}
Moving {steps} steps {direction}
{a} + {b} = {sum}Por exemplo, com uma mensagem say de "Hello world", um movimento de 5 passos na direção "north" e um cálculo de 10 e 25, a saída seria:
Saying: Hello world
Moving 5 steps north
10 + 25 = 35Você receberá cinco entradas: a mensagem say, a direção, o número de passos e os dois números a serem calculados.
Experimente você mesmo
mod command;
use command::Command;
fn main() {
// Ler entradas
let mut say_message = String::new();
std::io::stdin().read_line(&mut say_message).expect("Failed to read line");
let say_message = say_message.trim().to_string();
let mut direction = String::new();
std::io::stdin().read_line(&mut direction).expect("Failed to read line");
let direction = direction.trim().to_string();
let mut steps_input = String::new();
std::io::stdin().read_line(&mut steps_input).expect("Failed to read line");
let steps: u32 = steps_input.trim().parse().expect("Failed to parse steps");
let mut num1_input = String::new();
std::io::stdin().read_line(&mut num1_input).expect("Failed to read line");
let num1: i32 = num1_input.trim().parse().expect("Failed to parse num1");
let mut num2_input = String::new();
std::io::stdin().read_line(&mut num2_input).expect("Failed to read line");
let num2: i32 = num2_input.trim().parse().expect("Failed to parse num2");
// TODO: Criar um comando Say usando say_message e executá-lo
// TODO: Criar um comando Move usando direction e steps, e executá-lo
// TODO: Criar um comando Calculate usando num1 e num2, e executá-lo
// TODO: Imprimir os resultados de cada execução de comando
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
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 PlayerPratique por conta própria: Compilador de Rust online