Trait
trait 定义一种「类型能做什么」的抽象接口,类似其他语言的接口(interface)。它是 Rust 实现多态与代码复用核心。
1. 定义与实现 trait
trait Summary {
fn summarize(&self) -> String;
}
struct News {
headline: String,
}
impl Summary for News {
fn summarize(&self) -> String {
format!("头条: {}", self.headline)
}
}
fn main() {
let n = News { headline: String::from("Rust 1.0 发布") };
println!("{}", n.summarize());
}ℹ️trait 是能力契约
trait 只声明「有哪些方法」。一个类型 impl 了某 trait,就意味着它具备该能力,可被要求该能力的泛型/trait bound 接受。
2. 默认方法实现
trait Summary {
fn author(&self) -> String;
fn summarize(&self) -> String {
format!("(作者: {})", self.author()) // 默认实现可调用其他方法
}
}
impl Summary for News {
fn author(&self) -> String { String::from("编辑部") }
}3. trait 作为约束(trait bound)
fn notify<T: Summary>(item: &T) {
println!("通知: {}", item.summarize());
}也可用 impl Trait 简写:fn notify(item: &impl Summary)。
💡impl Trait vs 泛型 bound
fn f(x: &impl Trait) 与 fn f<T: Trait>(x: &T) 等价,前者更简洁,仅用于单约束单参数时。
4. trait 对象实现运行时多态
用 &dyn Trait 存放「任何实现了该 trait 的类型」,在运行时动态分发:
trait Summary {
fn summarize(&self) -> String;
}
struct News { headline: String }
struct Tweet { user: String }
impl Summary for News {
fn summarize(&self) -> String {
format!("头条: {}", self.headline)
}
}
impl Summary for Tweet {
fn summarize(&self) -> String {
format!("@{} 发推", self.user)
}
}
fn main() {
let news = News { headline: String::from("Rust 很快") };
let tweet = Tweet { user: String::from("alice") };
let items: Vec<&dyn Summary> = vec![&news, &tweet];
for i in items {
println!("{}", i.summarize());
}
}⚠️dyn 有运行时开销
dyn Trait 通过虚表(vtable)动态调用,有轻微开销且大小不固定(需指针)。若编译期多态够用,优先用泛型 + trait bound(静态分发,零开销)。
5. 派生 trait
用 #[derive(...)] 让编译器自动实现常用 trait:
#[derive(Debug, Clone, PartialEq)]
struct Point { x: i32, y: i32 }6. 返回 impl Trait
fn make_counter() -> impl FnMut() -> i32 {
let mut n = 0;
move || { n += 1; n }
}🎯练习
定义一个 trait Draw { fn draw(&self); },为 Circle 和 Square 实现它。写一个函数 fn render(shapes: &[&dyn Draw]) 遍历绘制。再给 trait 加一个默认方法 fn name(&self) -> &str { "unknown" }。
小结
- trait 抽象「能力」,类型用
impl实现 - 默认方法可复用;trait bound 约束泛型参数
impl Trait简写单约束;&dyn Trait实现运行时多态- 派生 trait 一键获得
Debug/Clone等 - 下一章看生命周期标注 →