Métodos por Default

Los traits pueden implementar comportamientos en función 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 los métodos implementados previamente (predeterminados) y los métodos que los usuarios deben implementar ellos mismos. Los métodos con implementaciones predeterminadas pueden basarse en métodos obligatorios.

  • Mueve el método not_equals a un nuevo trait NotEquals.

  • Haz que Equals sea un supertrait para NotEquals.

    trait NotEquals: Equals {
        fn not_equals(&self, other: &Self) -> bool {
            !self.equals(other)
        }
    }
  • Proporciona una implementación general de NotEquals para 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 necesitas Equals como supertrait para NotEqual.