Appearance
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,
}
}
}