Skip to content

Trait

Trait 描述类型具备的行为。类型通过 impl Trait for Type 加入实现。泛型用 trait bound 约束「能做什么」,而不是继承层级。

rust
trait Summary {
    fn summary(&self) -> String;

    fn peek(&self) -> String {
        self.summary()
    }
}

impl Summary for User {
    fn summary(&self) -> String {
        self.name.clone()
    }
}

默认方法可以在 trait 里提供实现,类型只覆盖需要定制的部分。

派生与手写

#[derive(Debug, Clone, ...)] 由编译器按字段生成实现,字段类型也必须满足对应 trait。行为无法由字段直接推出时手写 impl,例如 DisplayFrom

标准库里项目中最常碰到的:

Trait作用
Debug调试输出 {:?}
Display用户可见文本 {}
Clone / Copy显式复制 / 按位复制
Default默认值
From / TryFrom类型转换;? 依赖 From
Iteratorfor 循环与适配器
Drop离开作用域时的清理
Send / Sync跨线程移动 / 共享
Error可作为 ResultE

静态分发与动态分发

rust
fn print_static(s: impl Summary) {
    println!("{}", s.summary());
}

fn print_dyn(s: &dyn Summary) {
    println!("{}", s.summary());
}

impl Trait<T: Summary> 在编译期单态化,零开销,生成代码按具体类型展开。dyn Trait 是胖指针(数据指针 + 虚表),运行时分发,对象大小不固定,适合异质集合。

dyn Trait 本身不满足 Sized,通常写成 &dyn TraitBox<dyn Trait>

孤儿规则

Trait 或类型至少有一个在当前 crate 定义,才能写 impl Trait for Type。不能为外部类型实现外部 trait。需要给外部类型加方法时,用本地 newtype 包一层。

常用写法

rust
fn dump<T: Summary + std::fmt::Debug>(value: T) {
    println!("{:?} {}", value, value.summary());
}

impl From<u64> for UserId {
    fn from(id: u64) -> Self {
        Self(id)
    }
}

From 实现后自动获得 Into。应用代码优先 From / TryFrom,而不是散落转换函数。

基于 MIT 许可发布