跳过正文
  1. 知识笔记/

Rust学习01-所有权

·

Trait
#

trait(特征)是一种定义共享行为的机制,可以理解成其他语言中的接口,相当于是不管你底层是什么数据类型,只要定义了这个trait,就一定要实现这个trait的功能。

定义和实现
#

trait本质上是一组方法签名的集合,你可以定义一个trait并为不同的结构体去实现这个trait,代码实例如下

 1// 1. 定义一个名为 `MakeSound` 的 Trait,规定了必须有一个 `sound` 方法
 2pub trait MakeSound {
 3    fn sound(&self) -> String;
 4}
 5
 6// 2. 定义两个完全不同的结构体
 7struct Dog;
 8struct Cat;
 9
10// 3. 为 Dog 实现 `MakeSound` 契约
11impl MakeSound for Dog {
12    fn sound(&self) -> String {
13        String::from("汪汪!")
14    }
15}
16
17// 4. 为 Cat 实现 `MakeSound` 契约
18impl MakeSound for Cat {
19    fn sound(&self) -> String {
20        String::from("喵喵!")
21    }
22}

主要作用
#

trait主要的有下面几个特点

  • 多态:允许编写处理多种类型的通用代码,你可以写一个函数,不关心她是Dog还是Cat,只关心传入的类型能否make_sound
1// 这个函数接收任何实现了 MakeSound 的类型
2fn play_sound(animal: &impl MakeSound) {
3    println!("听到声音: {}", animal.sound());
4}
  • 泛型约束:trait可以来限制泛型能够接受的类型。例如<T:MakeSound>表示T可以是任何类型,但是必须实现了MakeSound这个trait。
  • 代码复用:trait中的方法可以有默认的实现逻辑,如果某个类型实现了trait但是没有重写方法,则会自动获得默认行为。

rust内置的trait
#

rust极其依赖trait,这也是rust设计优雅的原因,有很多理所当然的行为,实际上都是trait:

  • Debug和Display:可以使用println("{:?}",x)来打印变量。
  • Clone和Copy:定义了数据的复制
  • Add和Sub:定义了+-如何对非基础类型进行数学运算 rust的trait还符合开闭原则,即倘若要新增一个动物,无需重写playsound这个函数,而是直接新建一个动物结构体,并且为他impl MakeSound就可以了。 还体现了职责分离这一特点,MakeSound只负责发出声音,动物的逻辑只在动物的部分内,不同的模块就被安全的隔开了。

dyn
#