核心特性

第11课:trait与泛型

🎯 本课目标

掌握Rust trait定义、实现、泛型约束、trait对象和动态分发。

1. Trait定义与实现

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

    // 默认实现
    fn preview(&self) -> String {
        format!("{}...", &self.summarize()[..20.min(self.summarize().len())])
    }
}

struct Article { title: String, content: String }
struct Tweet { username: String, text: String }

impl Summary for Article {
    fn summarize(&self) -> String {
        format!("{}: {}", self.title, self.content)
    }
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!("@{}: {}", self.username, self.text)
    }
}

fn main() {
    let article = Article { title: "Rust".into(), content: "Rust is great".into() };
    println!("{}", article.summarize());
}

✅ 编译验证通过

2. 泛型与trait约束

// 泛型函数
fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in &list[1..] {
        if item > largest { largest = item; }
    }
    largest
}

// 多重约束
fn process<T: Clone + Display>(item: &T) -> String {
    let cloned = item.clone();
    format!("{}", cloned)
}

// where子句(更清晰)
fn some_function<T, U>(t: &T, u: &U) -> String
where
    T: Display + Clone,
    U: Clone + Debug,
{
    format!("{}", t)
}

// 泛型结构体
struct Pair<T> { x: T, y: T }

impl<T: PartialOrd> Pair<T> {
    fn cmp(&self) -> &T {
        if self.x >= self.y { &self.x } else { &self.y }
    }
}

fn main() {
    let nums = [1, 5, 3, 9, 2];
    println!("最大: {}", largest(&nums));
}

✅ 编译验证通过

3. Trait对象与动态分发

fn main() {
    // 静态分发(单态化)— 编译期确定类型
    fn notify_static<T: Summary>(item: &T) {
        println!("新闻: {}", item.summarize());
    }

    // 动态分发(trait对象)— 运行时查找
    fn notify_dynamic(item: &dyn Summary) {
        println!("新闻: {}", item.summarize());
    }

    // 异构集合
    let items: Vec<Box<dyn Summary>> = vec![
        Box::new(Article { title: "A".into(), content: "C".into() }),
        Box::new(Tweet { username: "u".into(), text: "t".into() }),
    ];
    for item in items {
        println!("{}", item.summarize());
    }
}

✅ 编译验证通过

静态 vs 动态分发: 静态(泛型): ┌──────────┐ 编译期生成 │ fn f_i32 │ ←── f<i32> 专用版本 │ fn f_f64 │ ←── f<f64> 专用版本 └──────────┘ 零开销,但代码膨胀 动态(trait对象): ┌──────┐ ┌──────────┐ │ data │────→│ 实际数据 │ │ vtable│───→│ 方法指针 │ 运行时查找 └──────┘ └──────────┘ 有开销,但灵活 vtable布局: ┌──────────────┐ │ drop指针 │ │ size │ │ alignment │ │ method1指针 │ │ method2指针 │ │ ... │ └──────────────┘

4. 常用标准trait

Trait用途运算符
From/Into类型转换
TryFrom/TryInto可能失败的转换
Display用户友好显示{}
Debug调试输出{:?}
Iterator迭代器for
Add/Sub/...运算符重载+ - * /
Deref解引用*
Drop析构函数

📝 练习题

练习1:实现Iterator

为自定义类型实现Iterator trait。

练习2:运算符重载

为复数类型实现Add、Sub、Mul。

练习3:Newtype与Deref

实现一个新类型并利用Deref实现透明委托。

🏆

成就解锁:抽象艺术家

掌握trait与泛型——Rust多态的核心


📚 扩展阅读

以下资源帮助你深入学习本课主题:

🔑 关键术语回顾

本课涉及的核心概念,确保你理解每一个:

术语说明
所有权Rust内存管理的核心机制,每个值有唯一所有者
借用通过引用访问数据,不获取所有权
生命周期引用有效的范围,编译期分析工具
traitRust的接口/抽象机制,类似其他语言的接口
泛型参数化类型,零成本抽象
模式匹配强大的数据解构和分支机制
零成本抽象高层抽象不引入运行时开销
fearless concurrency编译器保证线程安全

💬 学习建议

  1. 动手编码 — 每个代码示例都在本地运行一遍
  2. 修改实验 — 故意改错代码,看编译器报什么错
  3. 完成练习 — 每课的练习题是巩固知识的关键
  4. 阅读源码 — 看标准库和优秀开源项目的实现
  5. 写项目 — 真正掌握需要构建真实项目

🤔 常见问题

Q: Rust学习曲线真的很陡吗?

A: 前期确实需要适应所有权和借用检查器,但一旦理解了,这些概念会让你的代码更可靠。大多数人2-4周就能上手。

Q: Rust适合什么项目?

A: 系统编程、Web服务、CLI工具、嵌入式、WASM、网络服务、数据库等。基本上需要性能和安全的地方都适合。

Q: 遇到编译错误怎么办?

A: Rust编译器的错误信息非常友好!仔细阅读,通常会指出问题所在和修复建议。也可以用cargo clippy获取更多提示。