Enums con datos
Parte de la sección Programación Orientada a Objetos del Journey de Rust de Coddy. Lección 14 de 61.
Los enums básicos en Rust te permiten definir un tipo con un conjunto fijo de variantes, como Direction::North o Status::Active. Pero los enums de Rust son mucho más potentes que eso. Cada variante puede contener sus propios datos, lo que hace que los enums sean increíblemente flexibles para modelar situaciones del mundo real.
Considera un sistema de mensajería en el que distintos tipos de mensajes contienen información diferente. Un mensaje de texto tiene contenido, un comando de movimiento tiene coordenadas y una señal de salida no tiene nada en absoluto. En Rust, puedes representar todos estos casos con un solo enum:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(u8, u8, u8),
}
Cada variante tiene una forma diferente. Quit no contiene datos: es solo una señal.
Move utiliza una sintaxis similar a la de las estructuras, con campos con nombre. Write contiene un único String mediante una sintaxis de tupla. ChangeColor contiene tres valores que representan componentes RGB.
Crear instancias de estas variantes se ve así:
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);
La belleza de este enfoque es que m1, m2, m3 y m4 son todos del mismo tipo: Message. Puedes almacenarlos en la misma colección, pasarlos a la misma función o devolver cualquier variante desde una sola función. El enum unifica diferentes estructuras de datos bajo un mismo tipo, al tiempo que conserva la información específica que necesita cada variante.
Desafío
FácilConstruyamos un sistema de notificaciones que use enumeraciones con datos para representar distintos tipos de alertas. Cada tipo de notificación contiene información diferente: algunas tienen mensajes, otras tienen valores numéricos y otras son señales simples.
Crearás dos archivos para organizar tu código:
notification.rs: Define una enumeración públicaNotificationcon tres variantes:Alert: contiene un único mensajeString(sintaxis de tupla)Reminder: contiene campos con nombre:title(String) yminutes(u32)Dismiss: no contiene datos, solo es una señal
main.rs: Incorpora tu módulo de notificaciones y crea una instancia de cada variante. Después, imprime información sobre cada notificación para demostrar que las tres variantes son del mismo tipo, pero contienen datos diferentes.
Al imprimir, usa el formato de depuración ({:?}) para mostrar cada notificación. Tendrás que derivar el trait Debug en tu enumeración para poder imprimirla de esta manera.
Tu salida debe mostrar las tres notificaciones, cada una en su propia línea:
Alert("{message}")
Reminder { title: "{title}", minutes: {minutes} }
DismissPor ejemplo, con un mensaje de alerta "Server down", un recordatorio con el título "Meeting" y 30 minutos, la salida sería:
Alert("Server down")
Reminder { title: "Meeting", minutes: 30 }
DismissRecibirás tres entradas: el mensaje de alerta, el título del recordatorio y los minutos del recordatorio.
Pruébalo tú mismo
mod notification;
use notification::Notification;
fn main() {
// Leer 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: Crea una notificación Alert usando el alert_message
// TODO: Create a Reminder notification using reminder_title and reminder_minutes
// TODO: Crea una notificación Dismiss
// TODO: Imprime cada notificación usando el formato de depuración {:?}
// Cada notificación debe imprimirse en su propia línea
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
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 multimediaPractica por tu cuenta: Compilador de Rust online