运算符重载
学习目标
- 通过 trait 重载运算符
- 掌握常用运算符 trait
- 实现自定义类型的运算
核心概念
标准库运算符 Trait
use std::ops::{Add, Sub, Mul, Neg};
#[derive(Debug, Clone, Copy)]
struct Vector2D {
x: f64,
y: f64,
}
impl Add for Vector2D {
type Output = Self;
fn add(self, other: Self) -> Self {
Vector2D { x: self.x + other.x, y: self.y + other.y }
}
}
impl Sub for Vector2D {
type Output = Self;
fn sub(self, other: Self) -> Self {
Vector2D { x: self.x - other.x, y: self.y - other.y }
}
}
impl Mul<f64> for Vector2D {
type Output = Self;
fn mul(self, scalar: f64) -> Self {
Vector2D { x: self.x * scalar, y: self.y * scalar }
}
}
impl Neg for Vector2D {
type Output = Self;
fn neg(self) -> Self {
Vector2D { x: -self.x, y: -self.y }
}
}
fn main() {
let a = Vector2D { x: 1.0, y: 2.0 };
let b = Vector2D { x: 3.0, y: 4.0 };
println!("a + b = {:?}", a + b);
println!("a - b = {:?}", a - b);
println!("a * 2 = {:?}", a * 2.0);
println!("-a = {:?}", -a);
}
Display trait
use std::fmt;
struct Color {
r: u8,
g: u8,
b: u8,
}
impl fmt::Display for Color {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "#{:02x}{:02x}{:02x}", self.r, self.g, self.b)
}
}
impl fmt::Debug for Color {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Color(r={}, g={}, b={})", self.r, self.g, self.b)
}
}
fn main() {
let red = Color { r: 255, g: 0, b: 0 };
println!("Display: {}", red);
println!("Debug: {:?}", red);
}
Index 和 IndexMut
use std::ops::{Index, IndexMut};
struct Matrix {
data: Vec<Vec<f64>>,
rows: usize,
cols: usize,
}
impl Matrix {
fn new(rows: usize, cols: usize) -> Self {
Matrix {
data: vec![vec![0.0; cols]; rows],
rows,
cols,
}
}
}
impl Index<usize> for Matrix {
type Output = Vec<f64>;
fn index(&self, row: usize) -> &Vec<f64> {
&self.data[row]
}
}
impl IndexMut<usize> for Matrix {
fn index_mut(&mut self, row: usize) -> &mut Vec<f64> {
&mut self.data[row]
}
}
fn main() {
let mut m = Matrix::new(3, 3);
m[0][0] = 1.0;
m[1][1] = 2.0;
m[2][2] = 3.0;
println!("m[1][1] = {}", m[1][1]);
}
Deref trait
use std::ops::Deref;
struct MyString {
data: String,
}
impl Deref for MyString {
type Target = str;
fn deref(&self) -> &str {
&self.data
}
}
fn greet(name: &str) {
println!("Hello, {}!", name);
}
fn main() {
let s = MyString { data: String::from("Rust") };
greet(&s);
}
实践练习
练习 1:复数运算
use std::ops::{Add, Mul};
use std::fmt;
#[derive(Clone, Copy)]
struct Complex {
real: f64,
imag: f64,
}
impl Complex {
fn new(real: f64, imag: f64) -> Self {
Complex { real, imag }
}
}
impl Add for Complex {
type Output = Self;
fn add(self, other: Self) -> Self {
Complex {
real: self.real + other.real,
imag: self.imag + other.imag,
}
}
}
impl Mul for Complex {
type Output = Self;
fn mul(self, other: Self) -> Self {
Complex {
real: self.real * other.real - self.imag * other.imag,
imag: self.real * other.imag + self.imag * other.real,
}
}
}
impl fmt::Display for Complex {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} + {}i", self.real, self.imag)
}
}
fn main() {
let a = Complex::new(1.0, 2.0);
let b = Complex::new(3.0, 4.0);
println!("{} + {} = {}", a, b, a + b);
println!("{} × {} = {}", a, b, a * b);
}
常见错误
1. 忘记关联类型
小结
| Trait | 运算符 |
|---|
Add | + |
Sub | - |
Mul | * |
Div | / |
Neg | 一元 - |
Index | [] |
Display | {} |
Debug | {:?} |
Deref | 自动解引用 |