Coincidencia de variantes de datos
Parte de la sección Object Oriented Programming del Journey de Rust de Coddy — lección 16 de 61.
En la lección anterior, utilizaste match dentro de los métodos de enum para manejar diferentes variantes. Ahora enfoquémonos en cómo match extrae realmente los datos almacenados dentro de esas variantes, una técnica llamada desestructuración.
Cuando haces coincidir una variante de un enum que contiene datos, puedes vincular esos datos a variables directamente en el patrón:
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 brazo extrae datos de manera diferente según la estructura de la variante. Para las variantes de tipo estructura, se utiliza { field_name } para extraer campos con nombre. Para las variantes de tupla, se utilizan variables posicionales como (width, height).
Los nombres de las variables que elijas pasan a estar disponibles dentro de esa rama del match. Esto es potente porque estás comprobando simultáneamente qué variante tienes y obteniendo acceso a su contenido.
El compilador garantiza que manejes cada variante, y los valores extraídos están listos para usarse de inmediato; no se necesitan pasos adicionales.
Desafío
FácilVamos a construir un procesador de comandos que maneje diferentes tipos de comandos de usuario. Cada comando lleva datos diferentes, y tu procesador utilizará la coincidencia de patrones (pattern matching) para extraer esos datos y producir las respuestas adecuadas.
Crearás dos archivos para organizar tu código:
command.rs: Define un enum públicoCommandcon tres variantes:Say— contiene un único mensajeString(sintaxis de tupla)Move— contiene campos con nombre:direction(String) ysteps(u32)Calculate— contiene dos valoresi32que representan los números a sumar (sintaxis de tupla)
executeque utilicematchpara desestructurar cada variante y devolver unStringque describa la acción realizada.main.rs: Importa tu módulo de comandos, crea una instancia de cada variante de comando utilizando las entradas proporcionadas y llama al métodoexecuteen cada una para imprimir los resultados.
Tu método execute debe desestructurar cada variante para acceder a sus datos y devolver mensajes en estos formatos exactos:
- Para
Say:Saying: {message} - Para
Move:Moving {steps} steps {direction} - Para
Calculate:{a} + {b} = {sum}
Tu salida debe mostrar el resultado de cada comando en su propia línea:
Saying: {message}
Moving {steps} steps {direction}
{a} + {b} = {sum}Por ejemplo, con un mensaje de say de "Hello world", un movimiento de 5 pasos al "north", y un cálculo de 10 y 25, la salida sería:
Saying: Hello world
Moving 5 steps north
10 + 25 = 35Recibirás cinco entradas: el mensaje de say, la dirección, el número de pasos y los dos números para calcular.
Hoja de referencia
La coincidencia de patrones con match te permite desestructurar variantes de enum y extraer sus datos directamente en el patrón.
Para variantes de tupla, usa variables posicionales:
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 tipo estructura, usa la sintaxis de campos con nombre:
enum Event {
Click { x: i32, y: i32 },
}
match event {
Event::Click { x, y } => {
println!("Clicked at ({}, {})", x, y);
}
}Las variables extraídas pasan a estar disponibles dentro de su respectivo brazo de match, lo que te permite comprobar el tipo de variante y acceder a sus datos simultáneamente.
Pruébalo tú mismo
mod command;
use command::Command;
fn main() {
// Leer 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: Crear un comando Say usando say_message y ejecutarlo
// TODO: Crear un comando Move usando direction y steps, y ejecutarlo
// TODO: Crear un comando Calculate usando num1 y num2, y ejecutarlo
// TODO: Imprimir los resultados de la ejecución de cada comando
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
1Métodos y Comportamiento
Intro a Bloques de ImplementaciónEl Parámetro SelfMétodos MutablesFunciones AsociadasMúltiples Bloques de ImplementaciónEncadenamiento de MétodosResumen - Acciones de Rectángulo4Proyecto: Mascota virtual
Definir la mascotaAlimentar a la mascota7Traits estándar
El trait DebugEl trait DisplayClone y CopyTraits de igualdadResumen - Punto imprimible10Proyecto: Sistema de documentos
El Trait DrawComponente de texto2Encapsulamiento y módulos
Conceptos básicos de módulosLa palabra clave PublicCampos privadosGettersSettersRepaso - Casillero seguro5Genéricos
Estructuras genéricasMétodos genéricosMúltiples tipos genéricosFunciones genéricasResumen - Punto de coordenadas8Traits como límites
Sintaxis de límites de traitsLímites múltiplesLa cláusula whereRetornar tipos con traitsResumen: Impresora genérica11Patrones de diseño en Rust
Patrón NewtypeComposiciónEl Trait DropFrom e IntoResumen - Mock de Smart Pointer3Enums avanzados
Enums con datosMétodos en EnumsCoincidencia de variantes de datosEl Enum Option revisitadoResumen - Enum Shape6Definición de Traits
¿Qué es un Trait?Implementación de TraitsImplementaciones por defectoSobrescribir valores por defectoTraits con parámetrosResumen - Reproductor multimedia