اپراتورها

بارگذاری مجدد عملگرها از طریق traits در 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.

نکات بحث:

  • می‌توانید Add را برای Point& پیاده‌سازی کنید. در چه موقعیت‌هایی این کار مفید است؟
    • پاسخ: Add:add خود self را مصرف می‌کند. اگر تایپ T که برای آن عملگر را بارگذاری می‌کنید، Copy نباشد، باید پیاده‌سازی عملگر را برای T& نیز در نظر بگیرید. این کار از ایجاد کپی‌های غیرضروری در محل فراخوانی جلوگیری می‌کند.
  • چرا Output یک تایپ مرتبط است؟ آیا می‌توان آن را به‌عنوان یک پارامترتایپ برای متد تعریف کرد؟
    • پاسخ کوتاه: پارامترهای تایپ تابع توسط فراخوانی‌کننده کنترل می‌شوند، اما تایپ‌های مرتبط (مانند Output) توسط پیاده‌ساز trait کنترل می‌شوند.
  • شما می‌توانید Add را برای دو تایپ مختلف پیاده‌سازی کنید، به‌عنوان مثال impl Add<(i32, i32)> for Point می‌تواند یک tuple را به یک Point اضافه کند.

The Not trait (! operator) is notable because it does not "boolify" like the same operator in C-family languages; instead, for integer types it negates each bit of the number, which arithmetically is equivalent to subtracting it from -1: !5 == -6.