Límites múltiples
Parte de la sección Programación Orientada a Objetos del Journey de Rust de Coddy. Lección 41 de 61.
A veces, un único límite de rasgo no es suficiente. Es posible que necesites un tipo genérico que pueda imprimirse y proporcionar un resumen. Rust te permite requerir múltiples rasgos mediante la sintaxis +.
Así es como se especifica que un tipo debe implementar dos traits:
use std::fmt::Display;
trait Summary {
fn summarize(&self) -> String;
}
fn announce<T: Display + Summary>(item: T) {
println!("Breaking news: {}", item);
println!("Summary: {}", item.summarize());
}
La restricción T: Display + Summary significa «T debe implementar tanto Display como Summary». Dentro de la función, puedes usar capacidades de ambos traits: imprimir con {} (de Display) y llamar a summarize() (de Summary).
Puedes encadenar tantos rasgos como necesites:
fn process<T: Display + Summary + Clone>(item: T) {
// Puede imprimir, resumir Y clonar
}
Este patrón es esencial cuando tu función depende de varios comportamientos. En lugar de aceptar cualquier tipo y esperar que funcione, declaras explícitamente qué capacidades se requieren exactamente, y el compilador lo verifica en tiempo de compilación.
Desafío
Fácil¡Construyamos un sistema de inspección de productos que requiera que los artículos tengan varias capacidades! Crearás una función genérica que solo acepte tipos que implementen tanto un trait personalizado como un trait estándar, demostrando cómo la sintaxis + combina varios límites.
Organizarás tu código en dos archivos:
product.rs: Define un trait públicoInspectablecon un método llamadoinspectque recibe&selfy devuelve unStringque contiene los detalles de la inspección. Después, crea una estructura públicaGadgetcon campos públicosname(String) yserial(u32). Tu Gadget debe implementar tantoInspectable(devolviendoInspecting: {name}) comostd::fmt::Display(con el formato{name} (SN: {serial})). Finalmente, crea una función genérica pública llamadafull_reportque acepte cualquier tipoTque implemente tantoDisplaycomoInspectable. Esta función debe imprimir dos líneas: primero el artículo usando el formateador{}y después el resultado de llamar ainspect().main.rs: Incluye tu módulo de productos y crea una instancia deGadgetusando las entradas proporcionadas. Llama afull_reportcon tu gadget para demostrar que satisface ambos requisitos de traits.
El poder de los límites múltiples es que tu función full_report puede usar las capacidades de ambos traits, mostrando el artículo correctamente Y obteniendo los detalles de la inspección, todo ello garantizado en tiempo de compilación.
Tu salida debe mostrar tanto el formato de visualización como el resultado de la inspección:
{name} (SN: {serial})
Inspecting: {name}Por ejemplo, con las entradas Smartwatch y 98765:
Smartwatch (SN: 98765)
Inspecting: SmartwatchRecibirás dos entradas: el nombre del gadget y el número de serie (analízalo como u32).
Pruébalo tú mismo
mod product;
use product::{Gadget, full_report};
fn main() {
// Leer entradas
let mut name = String::new();
std::io::stdin().read_line(&mut name).expect("Failed to read line");
let name = name.trim().to_string();
let mut serial_input = String::new();
std::io::stdin().read_line(&mut serial_input).expect("Failed to read line");
let serial: u32 = serial_input.trim().parse().expect("Failed to parse serial");
// TODO: Crea una instancia de Gadget con el name y el serial
// TODO: Llama a full_report con tu gadget
}
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