跳过正文

2026-04-30

·

rust学习
#

今天的rust的学习主要是学了trait,我原本对trait的印象就是一个放在#[derive()]里面的,比如增加了Display或者Debug的trait之后,就可以直接在println里面打印结构体。

我今天主要学的就是重载运算符、Droptrait的特性。简单总结一下

trait
#

trait是什么,顾名思义,trait的中文是特征,即一种定义共享行为的机制,不管是什么数据类型,只要定义了这个trait,就一定要完成某个共享行为。比如说:DisplayDebugDrop…..对于绝大多数数据类型,这些trait都是满足的。 为什么要有trait?我自己总结下来有三点原因:

代码复用:
#

对于任何数据类型,他的同一个trait都可以有自己的实现方法,但是如果该数据类型没有自定义实现方法,可以通过trait得到一个默认的方法。

1trait Greet {
2    fn name(&self) -> String;
3    fn greet(&self) -> String {           // 默认实现
4        format!("Hello, {}!", self.name())
5    }
6}

泛型约束:
#

让函数接受"任何实现了某 trait 的类型",实现静态多态

1fn make_sound<T: Animal>(animal: &T) {
2    println!("{} says {}", animal.name(), animal.speak());
3}
4// 或用 impl Trait 语法(更简洁)
5fn make_sound(animal: &impl Animal) { ... }

编译器在编译之后就单态化他了。

动态分发:
#

使用dyn trait实现运行时的多态,可以在box里面存放不同的类型。

1let animals: Vec<Box<dyn Animal>> = vec![
2    Box::new(Dog),
3    Box::new(Cat),
4];
5for a in &animals {
6    println!("{}", a.speak()); // 运行时决定调用哪个实现
7}

dyn
#

具体说一下trait的动态分发的例子:

 1fn main() {
 2    let rn = 0.63;
 3    println!("{}", random_animal(rn).noise());
 4    println!("helloworld")
 5}
 6
 7struct Sheep {}
 8struct Cow {}
 9trait Animal {
10    fn noise(&self) -> &'static str;
11}
12impl Animal for Sheep {
13    fn noise(&self) -> &'static str {
14        "mie ~~~"
15    }
16}
17impl Animal for Cow {
18    fn noise(&self) -> &'static str {
19        "mou ~~~"
20    }
21}
22fn random_animal(rn: f64) -> Box<dyn Animal> {
23    if rn > 0.5 {
24        Box::new(Sheep {})
25    } else {
26        Box::new(Cow {})
27    }
28}

上面代码中,对于random_animal的返回,就使用了动态分发,不需要提前预设好类型,不需要指定是Sheep还是Cow