rust支持很多运算符,大致可以分为如下几类:

  • 赋值运算符
  • 比较运算符
  • 算术运算符
  • 解引用运算符

这里不介绍运算符的作用,而是介绍rust中运算符的重载。rust中的重载依靠trait完成。

赋值运算符

=
等于,在rusht中语义中默认是move的。move指的是所有权的转移。

比较运算符

==、!=、>、<、<=、>=。
==、!=运算符的重载依靠于std::cmp模块下的PartialEq和Eq。

PartialEq(部分相等)

需要实现的方法

eq

  1. fn eq(&self, other: &Rhs) -> bool

其中Rhs为一个泛型。
注:泛型是一些类型的集合,它通常和trait一起使用,通过trait来作为条件约束泛型。
实例:

  1. struct Point {
  2. order: u32,
  3. x: i32,
  4. y: i32,
  5. }
  6. impl PartialEq<u32> for Point {
  7. fn eq(&self, other: &u32) -> bool {
  8. self.order == *other
  9. }
  10. }
  11. fn main() {
  12. let one = Point {
  13. order: 1,
  14. x: 2,
  15. y: 3,
  16. };
  17. println!("{:?}", one == 2);
  18. }

自动实现的方法

ne

不等于。

Eq

一个标记trait,它的实现需要PartiaEq先实现,全等。
能体现这两种区别的是:浮点数之中特别数NAN, NAN和NAN不相等。

Ord

Ord用于实现类型之间值与值得比较

需要实现的方法

cmp

  1. fn cmp(&self, other: &Self) -> Ordering

自动实现的方法

max

返回两值中大值

min

返回小值

PartialOrd

PartialOrd用于>=,<=的重载。

需要实现的方法

partial_cmp

  1. fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>

在这个函数中Rhs为泛型,返回值为Option。Option为Option。其中Ordering为一个枚举。定义了大于,等于,小于三种状态。
注意:当此函数表示返回None,表示无法比较。
Ordering的定义如下

  1. pub enum Ordering {
  2. Less, //小于
  3. Equal,//等于
  4. Greater,//大于
  5. }

自动实现的方法

lt

小于

le

小于等于

gt

大于

ge

大于等于

算术运算符

除了比较运算符的trait处在std::cmp模块下,大多数运算符的重载位于std::ops模块。这里只介绍常用运算符的重载。

加法重载

加法运算依靠Add trait实现,其主要实现的方法如下:

  1. fn add(self, rhs: Rhs) -> Self::Output

在这个方法中,Rhs为一个泛型。需要注意的是Self::Output。这是trait的一种写法,叫做关联类型,它同样是泛型的一种限定,在实现此trait之前,我们必须指定它的关联类型,不是一种泛型,而是具体的类型。
具体实例如下:

  1. use std::ops::Add;
  2. #[derive(Debug)]
  3. struct Point {
  4. x: i32,
  5. y: i32,
  6. }
  7. impl Add for Point {
  8. type Output = Self;
  9. fn add(self, other: Self) -> Point {
  10. Point {
  11. x: self.x + other.x,
  12. y: self.y + other.y,
  13. }
  14. }
  15. }
  16. fn main() {
  17. let x = Point { x: 1, y: 1 };
  18. let y = Point { x: 2, y: 4 };
  19. let z = x + y;
  20. println!("{:?}", z);
  21. }

我们还可以实现这个例子的泛型版本,具体可以看官网的例子。减法等其他算术运算符的和加法类型。

解引用

解引用实现于Deref和DerefMut trait。这个trait的运用,可以方便使用指针类型后的值。其中DerefMut只用于智能指针的使用。
Deref需要实现的方法如下:

  1. fn deref(&self) -> &Self::Target

注意:如果T实现了Deref。x为T的值,那么下面三个方面自动实现:

  • x,自动实现为Deref::deref(&x)。如Deref trait实现的所示。x == Deref::deref(&x);x == &y,y为目标类型U的值。*x ==y。
  • &T 可强制转换为 &U。
  • T隐式实现了U类型的不可变方法,参数中只需要不可变引用的方法。

    其他

    其他比较特殊的trait是Fn/FnMut/FnOnce。这个等我们学习到闭包在谈。