Add în Rust

Trait-ul din spatele operatorului +; implementându-l, poți aduna valori ale tipurilor tale (bani, vectori).

Sintaxă
impl Add for Tip {
    type Output = Tip;
    fn add(self, other: Tip) -> Tip { ... }
}

Ce face Add

Operatorul a + b este de fapt Add::add(a, b). Implementând Add pentru un tip propriu, poți folosi + pe el. type Output spune ce tip are rezultatul (de obicei același tip). Parametrul generic Rhs permite ca partea dreaptă să fie de alt tip: impl Add<u32> for Bani.

Ceilalți operatori funcționează la fel: Sub (-), Mul (*), Div (/), Neg (-x), iar AddAssign pentru +=. Toate sunt în std::ops. add primește valorile prin mutare; pentru tipurile mici marchează-le Copy, ca să poți folosi operanzii și după adunare.

Parametri

Parametru Descriere
type Output Tipul rezultatului.
add(self, rhs) Calculul; consumă ambii operanzi.

Ce returnează

O valoare de tipul Output.

Exemple

Exemplul 1: Sume de bani

use std::fmt;
use std::ops::{Add, AddAssign};

#[derive(Clone, Copy)]
struct Bani(u64);   // în bani: 1 leu = 100 bani

impl Add for Bani {
    type Output = Bani;
    fn add(self, alt: Bani) -> Bani {
        Bani(self.0 + alt.0)
    }
}

impl AddAssign for Bani {
    fn add_assign(&mut self, alt: Bani) {
        self.0 += alt.0;
    }
}

impl fmt::Display for Bani {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{},{:02} lei", self.0 / 100, self.0 % 100)
    }
}

fn main() {
    let paine = Bani(450);
    let lapte = Bani(799);
    let total = paine + lapte;
    println!("{paine} + {lapte} = {total}");

    let mut cos = Bani(0);
    for p in [paine, lapte, Bani(1250)] {
        cos += p;
    }
    println!("coșul: {cos}");
}

Rezultat

4,50 lei + 7,99 lei = 12,49 lei
coșul: 24,99 lei

Exemplul 2: Vectori 2D și alt tip în dreapta

use std::ops::{Add, Mul};

#[derive(Debug, Clone, Copy, PartialEq)]
struct Vector {
    x: f64,
    y: f64,
}

impl Add for Vector {
    type Output = Vector;
    fn add(self, o: Vector) -> Vector {
        Vector { x: self.x + o.x, y: self.y + o.y }
    }
}

impl Mul<f64> for Vector {
    type Output = Vector;
    fn mul(self, k: f64) -> Vector {
        Vector { x: self.x * k, y: self.y * k }
    }
}

fn main() {
    let a = Vector { x: 1.0, y: 2.0 };
    let b = Vector { x: 0.5, y: -1.0 };
    println!("{:?}", a + b);
    println!("{:?}", (a + b) * 2.0);
    println!("{}", a + b == Vector { x: 1.5, y: 1.0 });
}

Rezultat

Vector { x: 1.5, y: 1.0 }
Vector { x: 3.0, y: 2.0 }
true

Greșeli frecvente

  • Uiți type Output: not all trait items implemented, missing: `Output`.
  • Folosești un operand după adunare la un tip care nu e Copy: use of moved value. Adaugă #[derive(Clone, Copy)] sau implementează Add pentru &Tip.

Comenzi înrudite

  • Index: Trait-ul din spatele operatorului container[i]; IndexMut permite și container[i] = valoare.
  • Copy: Trait marker pentru tipurile copiate automat bit cu bit la atribuire, în loc să fie mutate (numere, char, bool…).
  • fmt::Display: Trait-ul pentru afișarea către utilizator cu {}; se implementează manual și aduce automat to_string().