Operatörler

Operatör yüklemesi (overloading), std::ops’deki özellikler (traits) aracılığıyla gerçekleştirilir (implement):

#[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.

Tartışma noktaları:

  • &Point için Add’i gerçekleştirebilirsiniz (implement). Bu hangi durumlarda kullanışlıdır?
    • Cevap: Add:add, self’i tüketir. Operatörü yüklediğiniz T türü Copy değilse, operatörü &T için de yüklemey yapmayı (overloading) düşünmelisiniz. Bu, çağrı yerleride (call site) gereksiz klonlamayı önler.
  • Output neden bir ilişkili türdür (associated type)? Metodun bir tür parametresi yapılabilir miydi?
    • Kısa cevap: Fonksiyon tür parametreleri çağıran (caller) tarafından kontrol edilir, ancak ilişkili türler (Output gibi) bir özelliğin (trait) gerçekleştiricisi (implementer) tarafından kontrol edilir.
  • İki farklı tür için Add gerçekleştirebilirsiniz (implement), örn. impl Add<(i32, i32)> for Point, bu bir Point’e bir demet (tuple) eklerdi.

Not özelliği (! operatörü), C ailesi dillerindeki aynı operatör gibi “boole’laştırmadığı” için dikkat çekicidir; bunun yerine, tamsayı türleri için sayının her bitini olumsuzlar, bu da aritmetik olarak onu -1’den çıkarmaya eşdeğerdir: !5 == -6.