Skip to content

26.2 运算符重载

Rust 允许一部分运算符重载,用户可以让这些运算符支持自定义类型。运算符重载的方式是:针对自定义类型,impl 一些在标准库中预定义好的 trait,这些 trait 都存在于 std::ops 模块中。比如前面已经讲过了的 Deref trait 就属于运算符重载。

本章我们以最基本的 Add trait 来做讲解。Add 代表的是加法运算符 + 重载。它的定义是:


rust
trait Add<RHS = Self> {
    type Output;
    fn add(self, rhs: RHS) -> Self::Output;
}

它具备一个泛型参数 RHS 和一个关联类型 Output。其中 RHS 有一个默认值 Self。

标准库早已经为基本数字类型实现了这个 trait。比如:


rust
impl Add<i32> for i32 {
    type Output = i32;
}

而且还有:


rust
impl<'a> Add<i32> for &'a i32
    type Output = <i32 as Add<i32>>::Output;
impl<'a> Add<&'a i32> for i32
    type Output = <i32 as Add<i32>>::Output;
impl<'a, 'b> Add<&'a i32> for &'b i32
    type Output = <i32 as Add<i32>>::Output;

这意味着,不仅 i32+i32 是允许的,而且 i32+&i32、&i32+i32、&i32+&i32 这几种形式也都是允许的。它们的返回类型都是 i32。

假如我们现在自己定义了一个复数类型,想让它支持加法运算符,示例如下:


rust
use std::ops::Add;

#[derive(Copy, Clone, Debug, PartialEq)]
struct Complex {
    real : i32,
    imaginary : i32,
}

impl Add for Complex {
    type Output = Complex;

    fn add(self, other: Complex) -> Complex {
        Complex {
            real: self.real + other.real,
            imaginary: self.imaginary + other.imaginary,
        }
    }
}

fn main() {
    let c1 = Complex { real: 1, imaginary: 2};
    let c2 = Complex { real: 2, imaginary: 4};
    println!("{:?}", c1 + c2);
}

在这个实现中,我们没有指定泛型参数 RHS,所以它就采用了默认值,在此示例中就相当于 Complex 这个类型。同理,如果我们希望让这个复数能支持与更多的类型求和,可以继续写多个 impl:


rust
impl<'a> Add<&'a Complex> for Complex {
    type Output = Complex;

    fn add(self, other: &'a Complex) -> Complex {
        Complex {
            real: self.real + other.real,
            imaginary: self.imaginary + other.imaginary,
        }
    }
}

impl Add<i32> for Complex {
    type Output = Complex;

    fn add(self, other: i32) -> Complex {
        Complex {
            real: self.real + other,
            imaginary: self.imaginary,
        }
    }
}

Released under the MIT License