Menu
Coddy logo textTech

Despacho dinámico

Parte de la sección Programación Orientada a Objetos del Journey de Rust de Coddy. Lección 45 de 61.

Cuando usas genéricos con restricciones de traits como <T: Summary>, Rust determina el tipo exacto en tiempo de compilación. Esto se denomina despacho estático: el compilador genera código especializado para cada tipo concreto que usas. Es rápido, pero existe una limitación: una variable solo puede contener un tipo específico.

¿Qué pasa si necesitas una sola variable que pueda contener tipos diferentes en tiempo de ejecución? Aquí es donde entran en juego los objetos de rasgo. Usando Box<dyn Trait>, puedes almacenar cualquier tipo que implemente el rasgo:

trait Speak {
    fn speak(&self) -> String;
}

struct Dog;
struct Cat;

impl Speak for Dog {
    fn speak(&self) -> String { String::from("Woof!") }
}

impl Speak for Cat {
    fn speak(&self) -> String { String::from("Meow!") }
}

fn main() {
    let animal: Box<dyn Speak> = Box::new(Dog);
    println!("{}", animal.speak());  // "Woof!"
    
    let animal: Box<dyn Speak> = Box::new(Cat);
    println!("{}", animal.speak());  // "Meow!"
}

La palabra clave dyn indica el despacho dinámico: Rust busca qué method llamar en tiempo de ejecución en lugar de hacerlo en tiempo de compilación. Box es necesario porque los objetos de rasgo no tienen un tamaño conocido; Box proporciona un puntero con un tamaño fijo.

Piénsalo así: los genéricos dicen «trabajo con el tipo T», mientras que los objetos de rasgo dicen «trabajo con cualquier cosa que pueda hacer esto». La compensación es un pequeño coste en tiempo de ejecución a cambio de la flexibilidad de manejar distintos tipos mediante la misma variable.

challenge icon

Desafío

Fácil

¡Construyamos un sistema de alquiler de vehículos que demuestre el poder del despacho dinámico! Crearás un trait que define lo que cualquier vehículo alquilable puede hacer y, después, usarás Box<dyn Trait> para almacenar distintos tipos de vehículos en la misma variable.

Organizarás tu código en dos archivos:

  • vehicle.rs: Define un trait público Rentable con un método rental_info que recibe &self y devuelve un String. Después, crea dos structs públicos:
    • Car: con un campo público model (String). Su método rental_info debe devolver Car: {model}
    • Bike: con un campo público brand (String). Su método rental_info debe devolver Bike: {brand}
  • main.rs: Incluye tu módulo de vehículos y usa las entradas para demostrar el despacho dinámico. Crea una variable Box<dyn Rentable> que primero contenga un Car, imprime su información de alquiler, después reasigna la misma variable para que contenga un Bike e imprime de nuevo su información de alquiler.

La magia aquí es que una sola variable de tipo Box<dyn Rentable> puede contener un Car o un Bike: Rust determina qué método rental_info debe llamar en tiempo de ejecución. ¡Este es el despacho dinámico en acción!

Tu salida debe mostrar la información de ambos vehículos:

Car: {model}
Bike: {brand}

Por ejemplo, con las entradas Tesla Model 3 y Trek:

Car: Tesla Model 3
Bike: Trek

Recibirás dos entradas: el modelo del automóvil y la marca de la bicicleta.

Pruébalo tú mismo

mod vehicle;

use vehicle::{Rentable, Car, Bike};

fn main() {
    // Leer la entrada
    let mut car_model = String::new();
    std::io::stdin().read_line(&mut car_model).expect("Failed to read line");
    let car_model = car_model.trim().to_string();
    
    let mut bike_brand = String::new();
    std::io::stdin().read_line(&mut bike_brand).expect("Failed to read line");
    let bike_brand = bike_brand.trim().to_string();
    
    // TODO: Crea una variable Box<dyn Rentable> que contenga un Car
    // Imprime su información de alquiler usando el método rental_info()
    
    // TODO: Reasigna la misma variable para que contenga un Bike
    // Imprime su información de alquiler de nuevo
    
}
quiz iconPonte a prueba

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

Practica por tu cuenta: Compilador de Rust online