Operadores

La sobrecarga de operadores se implementa mediante traits en std::ops:

#[derive(Debug, Copy, Clone)]
struct Point {
    x: i32,
    y: i32,
}

impl std::ops::Add for Point {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        Self { x: self.x + other.x, y: self.y + other.y }
    }
}

fn main() {
    let p1 = Point { x: 10, y: 20 };
    let p2 = Point { x: 100, y: 200 };
    println!("{:?} + {:?} = {:?}", p1, p2, p1 + p2);
}
This slide should take about 5 minutes.

Cuestiones de debate:

  • ¿En qué situaciones sería útil implementar Add para &Point?
    • Respuesta: Add:add consume a self. Si el tipo T para el que se sobrecarga el operador no es Copy, deberías plantearte también sobrecargar el operador para &T. Así se evita la clonación innecesaria en el sitio de la llamada.
  • ¿Por qué Output es un tipo asociado? ¿Se podría convertir en un parámetro tipo del método?
    • Respuesta corta: el llamador controla los parámetros tipo de la función, pero los tipos asociados (como Output) son controlados por el implementador de un trait.
  • Se podría implementar Add para dos tipos distintos; por ejemplo, impl Add<(i32, i32)> for Point añadiría una tupla a un Point.