Files
rust/Trait/readme.md
2025-10-05 23:51:24 +08:00

289 lines
6.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

非常好 👍!
`trait` 是 Rust 中非常核心、非常强大的概念之一,几乎等价于 C++ 的「接口interface」或「抽象基类abstract base class
但 Rust 的 `trait` 更安全、更灵活、还能与泛型深度结合。
下面我们来**从直觉 → 语法 → 实战 → 泛型结合 → 高级技巧**系统地讲清楚 Rust 的 `trait` 怎么用。
---
## 🧩 一、Trait 是什么?
一句话解释:
> **Trait 定义了一组类型必须实现的“能力”或“行为”**。
比如“能打印”、“能比较大小”、“能移动”等行为,都可以用 `trait` 定义。
---
## 🧠 二、最简单的 trait 示例
```rust
trait Summary {
fn summarize(&self) -> String;
}
```
上面定义了一个 `Summary` 特征trait它表示“这个类型能生成一个概要字符串”。
任何想拥有这个功能的类型,都要实现它。
---
## 💡 三、为结构体实现 trait
```rust
struct NewsArticle {
title: String,
author: String,
content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{} by {}", self.title, self.author)
}
}
```
现在,`NewsArticle` 类型就有了 `.summarize()` 方法:
```rust
fn main() {
let article = NewsArticle {
title: String::from("Rust trait 学习指南"),
author: String::from("Evan"),
content: String::from("内容..."),
};
println!("{}", article.summarize());
}
```
✅ 输出:
```
Rust trait 学习指南 by Evan
```
---
## 🔧 四、Trait = 行为接口(类比 C++
| 概念 | Rust | C++ 类似 |
| ---- | -------------------------------- | -------------------------------------------- |
| 定义接口 | `trait Summary { ... }` | `class Summary { virtual ... = 0; }` |
| 实现接口 | `impl Summary for NewsArticle` | `class NewsArticle : public Summary { ... }` |
| 调用接口 | `item.summarize()` | `item.summarize()` |
| 多态传参 | `fn notify(item: &impl Summary)` | `void notify(const Summary& item)` |
---
## ⚙️ 五、trait 作为函数参数(多态)
```rust
fn notify(item: &impl Summary) {
println!("Breaking news! {}", item.summarize());
}
```
这个函数可以接受**任何实现了 `Summary` 的类型**
```rust
let article = NewsArticle {
title: String::from("Rust 1.80 发布!"),
author: String::from("官方"),
content: String::from("..."),
};
notify(&article);
```
---
## 🔄 六、与泛型结合的写法
等价的更通用写法是:
```rust
fn notify<T: Summary>(item: &T) {
println!("Breaking news! {}", item.summarize());
}
```
这两种写法效果一致:
* `fn foo(x: &impl Trait)`:语法糖
* `fn foo<T: Trait>(x: &T)`:完整泛型写法,可组合多个 trait
---
## 🧩 七、多个 trait 约束
如果希望一个类型实现多个 trait 才能传入:
```rust
fn show<T: Summary + Clone>(item: &T) {
println!("{}", item.summarize());
}
```
或者更清晰的写法:
```rust
fn show<T>(item: &T)
where
T: Summary + Clone,
{
println!("{}", item.summarize());
}
```
---
## 🔁 八、Trait 默认实现
trait 还可以提供**默认方法实现**
```rust
trait Summary {
fn summarize(&self) -> String {
String::from("(Read more...)")
}
}
```
实现时可以选择覆盖它:
```rust
impl Summary for NewsArticle {
// 也可以不写 summarize(),直接用默认实现
}
```
---
## 🧩 九、返回实现 trait 的类型impl Trait 返回)
函数也可以**返回实现某个 trait 的类型**
```rust
fn make_article() -> impl Summary {
NewsArticle {
title: String::from("Hello"),
author: String::from("Rust"),
content: String::from("..."),
}
}
```
这里的 `impl Summary` 意思是“返回一个实现了 `Summary` 的对象”,
但不能同时返回多种不同类型(必须一致)。
---
## 💥 十、trait 对象(动态分发)
如果你希望“一个变量”能存放**多种类型但都有共同 trait**,用 `Box<dyn Trait>`
```rust
fn main() {
let article = NewsArticle {
title: String::from("Rust"),
author: String::from("Evan"),
content: String::from("..."),
};
let tweet = Tweet {
username: String::from("rustacean"),
content: String::from("trait 太强了"),
};
let items: Vec<Box<dyn Summary>> = vec![
Box::new(article),
Box::new(tweet),
];
for i in items {
println!("{}", i.summarize());
}
}
```
这就类似于 C++ 的虚函数表vtable动态多态。
---
## 🧩 十一、完整例子trait、泛型、多态一起
```rust
trait Summary {
fn summarize(&self) -> String;
}
struct NewsArticle {
title: String,
author: String,
}
struct Tweet {
username: String,
content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{} by {}", self.title, self.author)
}
}
impl Summary for Tweet {
fn summarize(&self) -> String {
format!("@{}: {}", self.username, self.content)
}
}
fn notify<T: Summary>(item: &T) {
println!("Breaking news! {}", item.summarize());
}
fn main() {
let tweet = Tweet {
username: String::from("EvanZ"),
content: String::from("Rust trait 学到了!"),
};
let article = NewsArticle {
title: String::from("学习 Rust 的一天"),
author: String::from("Evan"),
};
notify(&tweet);
notify(&article);
}
```
输出:
```
Breaking news! @EvanZ: Rust trait 学到了!
Breaking news! 学习 Rust 的一天 by Evan
```
---
## ✅ 十二、总结表
| 功能 | 语法 | 含义 |
| -------- | ------------------------------------------------ | ---------------- |
| 定义 trait | `trait TraitName { fn func(&self); }` | 定义行为接口 |
| 实现 trait | `impl TraitName for Type { ... }` | 给类型实现行为 |
| 参数约束 | `fn f<T: Trait>(t: &T)``fn f(t: &impl Trait)` | 仅接受实现了 Trait 的类型 |
| 多 trait | `T: TraitA + TraitB` | 同时要求多个行为 |
| 返回 trait | `-> impl Trait` | 返回实现了该行为的类型 |
| 动态多态 | `Box<dyn Trait>` | 在运行时存放不同实现 |
| 默认实现 | `fn func(&self) { ... }` | 允许被覆盖或继承默认功能 |
---
是否希望我接着讲讲 **trait 与泛型的底层机制**(即静态分发 vs 动态分发的区别),包括它们的性能差异与编译原理?(这部分对理解 Rust trait 的“真功夫”非常有帮助)