Menu
Coddy logo textTech

Implementaciones por defecto

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

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

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 método, 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 {} vacío es válido porque el trait ya proporciona el comportamiento. La estructura simplemente «opta por» el trait y recibe el método predeterminado de forma gratuita.

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

challenge icon

Desafío

Fácil

¡Exploremos el poder de las implementaciones predeterminadas creando un sistema de notificaciones! Crearás un trait que proporciona un comportamiento estándar desde el principio, para que los tipos puedan optar por él 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 predeterminada. La implementación predeterminada 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 estructuras unitarias públicas sencillas que implementen tu trait:
    • EmailAlert: implementa Notifiable con un bloque impl vacío (usa la implementación predeterminada)
    • SystemAlert: también implementa Notifiable con un bloque impl vacío (usa la implementación predeterminada)
    Ambas estructuras obtendrán automáticamente el mensaje de notificación predeterminado sin que escribas 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 predeterminado. Crea instancias de ambas estructuras 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 predeterminadas! Ninguna de las dos estructuras necesitó escribir código para el método notify, pero ambas tienen un comportamiento de notificación completamente funcional. En la próxima lección, aprenderás a sobrescribir estas implementaciones predeterminadas 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 Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Rust online