Rust Trait

trait 定义共享行为;impl Trait for Type 提供实现;bound 约束泛型;与接口/类型类的对照。

#type / concept #status / growing #tech / dev #resource / rust

[!info] 关联笔记

Rust Trait

这个概念为什么出现

不同的类型需要同一套能力:可摘要、可序列化、可迭代、可比较。
Rust 不用继承树挂方法,而用 trait 声明行为,再为具体类型实现。

[!abstract] 一句话理解 trait 是行为契约;impl Trait for Type 提供实现;泛型上的 T: Trait 把契约变成编译期约束。

最小可运行示例

场景:通知中心——邮件与短信都能 send

运营系统要对用户发通知,渠道不同但都要 send。用 trait 统一调用面。

// 业务意图:统一通知发送接口,屏蔽渠道差异。
// 教学点:trait 定义、为结构体实现、泛型 bound、&dyn Trait 点到为止。

trait Notifier {
    fn send(&self, user_id: u64, body: &str);
}

struct EmailNotifier { from: String }
struct SmsNotifier { sender_id: String }

impl Notifier for EmailNotifier {
    fn send(&self, user_id: u64, body: &str) {
        println!("email from={} user={} body={}", self.from, user_id, body);
    }
}

impl Notifier for SmsNotifier {
    fn send(&self, user_id: u64, body: &str) {
        println!("sms sender={} user={} body={}", self.sender_id, user_id, body);
    }
}

// 静态分发:编译期单态化
fn notify_all<N: Notifier>(n: &N, user_id: u64, body: &str) {
    n.send(user_id, body);
}

fn main() {
    let email = EmailNotifier { from: String::from("noreply@shop") };
    let sms = SmsNotifier { sender_id: String::from("SHOP") };
    notify_all(&email, 7, "order shipped");
    notify_all(&sms, 7, "order shipped");
}

建议运行:cargo run

期望输出:

email from=noreply@shop user=7 body=order shipped
sms sender=SHOP user=7 body=order shipped

结合场景再看三个关注点

  1. 调用方依赖 trait 而非具体渠道
  2. 泛型 bound 零成本静态分发
  3. 需要异构集合时再引入 dyn Notifier(进阶)

核心概念与准确模型

定义与实现

trait Summary {
    fn summarize(&self) -> String;
    fn prefix(&self) -> String { // 默认实现
        String::from("(summary)")
    }
}

派生与标准 trait

常见:DebugCloneDefaultPartialEqIteratorFrom/Into

约束写法

  • fn f<T: Clone + Debug>(x: T)
  • where 子句更清晰

静态分发 vs 动态分发

  • 泛型:impl Trait / T: Trait → 单态化
  • trait 对象:dyn Trait → 虚表,对象安全有限制

设计动机

  • 组合行为,避免深层继承
  • 孤儿规则等限制保证 trait 实现的一致性
  • 与泛型一起支撑零成本抽象

边界与误区

  • 不能对外部类型实现外部 trait(孤儿规则)
  • 默认方法可重写
  • trait 对象方法接收者限制

[!warning] 常见误区:把 trait 当 Java interface 的 1:1 有默认方法、关联类型、泛型方法等更丰富机制;对象安全也不同。

工程实践

  1. 小而专的 trait 优于上帝接口
  2. 公共 API 用 trait 隐藏实现
  3. 能静态分发就不要无 dyn 换间接层
  4. 善用 From/TryFrom 做转换契约

本节总结

  • trait 定义能力
  • impl 提供实现
  • bound 约束泛型
  • 静态/动态分发按需

自测题

  1. T: Notifier&dyn Notifier 主要差别?
  2. 为什么需要默认实现?
参考答案
  1. 前者单态化静态分发;后者运行时多态、有对象安全约束。
  2. 减少样板,同时保留可覆盖点。

延伸阅读与资料来源

资料类型支撑内容
The Book — Traits官方书trait
Rust By Example — Traits官方示例
创建于 2026/7/15 更新于 2026/7/15