Menu
Coddy logo textTech

Implementaciones por defecto

Parte de la sección Object Oriented Programming del Journey de Rust de Coddy. Lección 31 de 61.

Hasta ahora, todos los métodos de trait que hemos definido han sido solo una firma: un requisito sin cuerpo. Pero ¿qué ocurre si la mayoría de los tipos que implementan un trait usarían la misma lógica? Rust te permite proporcionar una implementación predeterminada directamente en la definición del trait.

En lugar de terminar la firma del método con un punto y coma, añades un cuerpo:

trait Greet {
    fn greet(&self) -> String {
        String::from("Hello there!")
    }
}

Ahora cualquier tipo que implemente Greet obtiene automáticamente este method, sin escribir ningún código en el bloque impl:

struct Guest;

impl Greet for Guest {}

let visitor = Guest;
println!("{}", visitor.greet());  // ¡Hola!

El impl Greet for Guest {} empty es válido porque el trait ya proporciona el comportamiento. El struct simplemente se «inscribe» en el trait y recibe el método default gratis.

Este patrón es útil cuando quieres definir un comportamiento compartido que funcione para la mayoría de los casos. Los tipos que necesiten algo diferente pueden sobrescribir el comportamiento default (que aprenderás a continuación), mientras que los tipos conformes con el comportamiento estándar no necesitan repetirse.

challenge icon

Desafío

Fácil

¡Exploremos el poder de las implementaciones default construyendo un sistema de notificaciones! Crearás un trait que proporciona un comportamiento estándar listo para usar, de modo que los tipos puedan adoptarlo sin escribir código repetitivo.

Organizarás tu código en tres archivos:

  • notifiable.rs: Define un trait público Notifiable con un método notify(&self) -> String que tiene una implementación default. El valor predeterminado debe devolver "You have a new notification!". Cualquier tipo que implemente este trait recibirá automáticamente este comportamiento sin necesidad de escribir nada en su bloque impl.
  • alerts.rs: Crea dos structs unitarios públicos simples que implementen tu trait:
    • EmailAlert: implementa Notifiable con un bloque impl vacío (usa el valor predeterminado)
    • SystemAlert: también implementa Notifiable con un bloque impl vacío (usa el valor predeterminado)
    Ambos structs obtendrán automáticamente el mensaje de notificación default sin que tengas que escribir ningún cuerpo de método.
  • main.rs: Reúne tus módulos y demuestra cómo ambos tipos de alerta comparten el mismo comportamiento default. Crea instancias de ambos structs y llama a sus métodos notify.

En tu archivo principal, crea un EmailAlert y un SystemAlert, y después imprime sus notificaciones en líneas separadas.

Tu salida debe ser:

You have a new notification!
You have a new notification!

Observa cómo ambos tipos producen una salida idéntica: ¡esa es la belleza de las implementaciones default! Ninguno de los dos structs necesitó escribir código para el método notify, y aun así ambos tienen un comportamiento de notificación completamente funcional. En la próxima lección, aprenderás a sobrescribir estos valores predeterminados cuando un tipo necesite un comportamiento personalizado.

Pruébalo tú mismo

mod notifiable;
mod alerts;

use notifiable::Notifiable;
use alerts::{EmailAlert, SystemAlert};

fn main() {
    // TODO: Crea una instancia de EmailAlert
    
    // TODO: Crea una instancia de SystemAlert
    
    // TODO: Print the notification from EmailAlert
    
    // TODO: Print the notification from SystemAlert
}
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 Object Oriented Programming

Practica por tu cuenta: Compilador de Rust online