Menu
Coddy logo textTech

Correspondência de Variantes de Dados

Parte da seção Object Oriented Programming 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 focar em como o match realmente extrai os dados armazenados dentro dessas variantes — uma técnica chamada desestruturação.

Quando você faz o match em uma variante de enum que contém dados, você 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 do tipo struct, 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ê escolhe tornam-se disponíveis dentro daquele braço do match. Isso é poderoso porque você está simultaneamente verificando qual variante você tem e obtendo acesso ao seu payload.

O compilador garante que você trate cada variante, e os valores extraídos estão prontos para uso imediato — sem etapas extras necessárias.

challenge icon

Desafio

Fácil

Vamos construir um processador de comandos que lida com diferentes tipos de comandos de usuário. Cada comando carrega dados diferentes, e seu processador usará correspondência de padrões (pattern matching) para extrair esses dados e produzir as respostas apropriadas.

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

  • command.rs: Defina um enum Command público com três variantes:
    • Say — contém uma única mensagem String (sintaxe de tupla)
    • Move — contém campos nomeados: direction (String) e steps (u32)
    • Calculate — contém dois valores i32 representando números para somar (sintaxe de tupla)
    Em seguida, implemente um método execute que use match para desestruturar cada variante e retornar uma String descrevendo a ação realizada.
  • main.rs: Importe seu módulo de comando, crie uma instância de cada variante de comando usando as entradas fornecidas e chame o método execute em 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 de say de "Hello world", um move de 5 passos para "north", e um cálculo de 10 e 25, a saída seria:

Saying: Hello world
Moving 5 steps north
10 + 25 = 35

Você receberá cinco entradas: a mensagem de say, a direção, o número de passos e os dois números para calcular.

Folha de consulta

A correspondência de padrões com match permite que você desestruture variantes de enum e extraia seus dados diretamente no padrão.

Para variantes de tupla, use variáveis posicionais:

enum Event {
    KeyPress(char),
    Resize(u32, u32),
}

match event {
    Event::KeyPress(key) => {
        println!("Key: {}", key);
    }
    Event::Resize(width, height) => {
        println!("{}x{}", width, height);
    }
}

Para variantes do tipo struct, use a sintaxe de campos nomeados:

enum Event {
    Click { x: i32, y: i32 },
}

match event {
    Event::Click { x, y } => {
        println!("Clicked at ({}, {})", x, y);
    }
}

As variáveis extraídas tornam-se disponíveis dentro de seu respectivo braço de correspondência, permitindo que você verifique o tipo da variante e acesse seus dados simultaneamente.

Experimente você mesmo

mod command;

use command::Command;

fn main() {
    // Ler as 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
}
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