Translate

lunes, 16 de octubre de 2023

Default Methods en Rust


Los traits pueden implementar el comportamiento en términos de otros métodos de traits:

trait Equals {

    fn equals(&self, other: &Self) -> bool;

    fn not_equals(&self, other: &Self) -> bool {

        !self.equals(other)

    }

}


#[derive(Debug)]

struct Centimeter(i16);


impl Equals for Centimeter {

    fn equals(&self, other: &Centimeter) -> bool {

        self.0 == other.0

    }

}


fn main() {

    let a = Centimeter(10);

    let b = Centimeter(20);

    println!("{a:?} equals {b:?}: {}", a.equals(&b));

    println!("{a:?} not_equals {b:?}: {}", a.not_equals(&b));

}


Los traits pueden especificar métodos preimplementados (predeterminados) y métodos que los usuarios deben implementar ellos mismos. Los métodos con implementaciones predeterminadas pueden depender de los métodos requeridos. Por ejemplo podemos implementar un trait NotEquals y mover el método not_equals a este y hacer de Equals un súper rasgo para NotEquals.


trait NotEquals: Equals {

    fn not_equals(&self, other: &Self) -> bool {

        !self.equals(other)

    }

}

O podemos proporcionar una implementación general de NotEquals, y especificar una implementación para todos los que implementen Equals.

trait NotEquals {

    fn not_equals(&self, other: &Self) -> bool;

}


impl<T> NotEquals for T where T: Equals {

    fn not_equals(&self, other: &Self) -> bool {

        !self.equals(other)

    }

}

Con la implementación general, ya no necesita a Equals como un trait general para NotEqual.