rust学习#
今天的rust的学习主要是学了
trait,我原本对trait的印象就是一个放在#[derive()]里面的,比如增加了Display或者Debug的trait之后,就可以直接在println里面打印结构体。
我今天主要学的就是重载运算符、Drop和trait的特性。简单总结一下
trait#
trait是什么,顾名思义,trait的中文是特征,即一种定义共享行为的机制,不管是什么数据类型,只要定义了这个trait,就一定要完成某个共享行为。比如说:Display、Debug、Drop…..对于绝大多数数据类型,这些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。