journal

2026-04-30

rust学习

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

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

trait

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

代码复用:

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

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

泛型约束:

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

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

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

动态分发:

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

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

dyn

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

fn main() {
    let rn = 0.63;
    println!("{}", random_animal(rn).noise());
    println!("helloworld")
}

struct Sheep {}
struct Cow {}
trait Animal {
    fn noise(&self) -> &'static str;
}
impl Animal for Sheep {
    fn noise(&self) -> &'static str {
        "mie ~~~"
    }
}
impl Animal for Cow {
    fn noise(&self) -> &'static str {
        "mou ~~~"
    }
}
fn random_animal(rn: f64) -> Box<dyn Animal> {
    if rn > 0.5 {
        Box::new(Sheep {})
    } else {
        Box::new(Cow {})
    }
}

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

评论

注册或登录后即可评论。

评论将在接近此处时加载。