Rasgos

Un trait es una colección de métodos definidos para un tipo desconocido: Self. Pueden acceder a otros métodos declarados en el mismo rasgo.

Los rasgos se pueden implementar para cualquier tipo de datos. En el siguiente ejemplo, definimos Animal, un grupo de métodos. A continuación, se implementa el trait Animal para el tipo de datos Oveja, lo que permite el uso de métodos de Animal con una Oveja.

struct Oveja { trasquilada: bool, nombre: &'static str }

trait Animal {
    // Signatura del método estático; `Self` se refiere al tipo del implementador.
    fn new(nombre: &'static str) -> Self;

    // Signatura del método de instancia; estos devolverán una cadena.
    fn nombre(&self) -> &'static str;
    fn sonido(&self) -> &'static str;

    // Los rasgos pueden proporcionar definiciones de método predeterminadas.
    fn habla(&self) {
        println!("{} dice {}", self.nombre(), self.sonido());
    }
}

impl Oveja {
    fn esta_trasquilada(&self) -> bool {
        self.trasquilada
    }

    fn trasquila(&mut self) {
        if self.esta_trasquilada() {
            // Los métodos del implementador pueden usar los métodos de rasgos del
            // implementador.
            println!("{} ya está trasquilada...", self.nombre());
        } else {
            println!("{} va a ser trasquilada!", self.nombre);

            self.trasquilada = true;
        }
    }
}

// Implement the `Animal` trait for `Oveja`.
impl Animal for Oveja {
    // `Self` es el tipo de implementador: `Oveja`.
    fn new(nombre: &'static str) -> Oveja {
        Oveja { nombre: nombre, trasquilada: false }
    }

    fn nombre(&self) -> &'static str {
        self.nombre
    }

    fn sonido(&self) -> &'static str {
        if self.esta_trasquilada() {
            "baaaaah?"
        } else {
            "baaaaah!"
        }
    }
    
    // Se pueden anular los métodos de rasgos predeterminados.
    fn habla(&self) {
        // Por ejemplo, podemos agregar algo de contemplación tranquila.
        println!("{} hace una breve pausa... {}", self.nombre, self.sonido());
    }
}

fn main() {
    // La anotación de tipo es necesaria en este caso.
    let mut dolly: Oveja = Animal::new("Dolly");
    // TODO ^ Intenta eliminar las anotaciones de tipo.

    dolly.habla();
    dolly.trasquila();
    dolly.habla();
}