
Rust 的灵魂:定义、实现、默认实现、作为参数/返回值
如果你学过 Java 或 C#,Trait 大概就是"接口"的亲戚。如果你学过 Python,Trait 有点像"协议"。但 Rust 的 Trait 比它们都强大!
我刚开始学 Rust 的时候,看到 Trait 就想:"这不就是接口吗?有啥特别的?"后来才发现,Trait 是 Rust 类型系统的灵魂——泛型约束靠它、多态靠它、代码复用靠它,连运算符重载都靠它!
没有 Trait,Rust 就是一堆死板的类型;有了 Trait,这些类型才能"说话",才能被泛型代码使用。今天咱们就搞清楚 Trait 到底是什么,怎么用。
Trait 定义了一组行为(方法),任何类型只要实现了这些方法,就说它"实现了这个 Trait"。
想象一下"会叫"这个 Trait:
它们叫的方式不同,但都实现了"会叫"这个行为。
特性 | Rust Trait | Java 接口 |
|---|---|---|
默认实现 | ✅ 可以有 | ✅ 可以有 (Java 8+) |
字段 | ❌ 不能有 | ✅ 可以有常量 |
多重实现 | ✅ 可以实现多个 | ✅ 可以实现多个 |
运算符重载 | ✅ 可以 | ❌ 不可以 |
作为类型 | ✅ Trait 对象 | ✅ 接口类型 |
// 定义 Trait
trait Speak {
fn speak(&self);
}
// 实现 Trait
struct Dog;
struct Cat;
impl Speak for Dog {
fn speak(&self) {
println!("汪汪汪!");
}
}
impl Speak for Cat {
fn speak(&self) {
println!("喵喵喵!");
}
}
fn main() {
let dog = Dog;
let cat = Cat;
dog.speak(); // 汪汪汪!
cat.speak(); // 喵喵喵!
}
trait Greet {
fn greet(&self) {
println!("你好!"); // 默认实现
}
fn greet_formal(&self); // 必须实现
}
struct Person {
name: String,
}
impl Greet for Person {
// 使用默认的 greet()
fn greet_formal(&self) {
println!("尊敬的 {} 先生/女士,您好!", self.name);
}
}
fn main() {
let person = Person { name: "张三".to_string() };
person.greet(); // 你好!(默认实现)
person.greet_formal(); // 尊敬的 张三 先生/女士,您好!
}
trait Drawable {
fn draw(&self);
}
struct Circle;
struct Rectangle;
impl Drawable for Circle {
fn draw(&self) {
println!("画一个圆");
}
}
impl Drawable for Rectangle {
fn draw(&self) {
println!("画一个矩形");
}
}
// 泛型函数:T 必须实现 Drawable
fn draw_item<T: Drawable>(item: T) {
item.draw();
}
// 多个 Trait 约束
fn process<T: Drawable + Clone>(item: T) {
item.draw();
let _copy = item.clone();
}
fn main() {
draw_item(Circle);
draw_item(Rectangle);
}
trait Animal {
fn make_sound(&self);
}
struct Dog;
struct Cat;
impl Animal for Dog {
fn make_sound(&self) {
println!("汪汪!");
}
}
impl Animal for Cat {
fn make_sound(&self) {
println!("喵喵!");
}
}
// 返回具体类型
fn get_dog() -> impl Animal {
Dog
}
// 返回 Trait 对象(动态大小)
fn get_animal(is_dog: bool) -> Box<dyn Animal> {
if is_dog {
Box::new(Dog)
} else {
Box::new(Cat)
}
}
fn main() {
let animal = get_animal(true);
animal.make_sound();
}
use std::fmt::Display;
struct Point {
x: i32,
y: i32,
}
// 为标准库的 Display trait 实现
impl Display for Point {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Point({}, {})", self.x, self.y)
}
}
fn main() {
let p = Point { x: , y: };
println!("{}", p); // Point(3, 4)
}
use std::fmt::{Display, Debug};
// 方式 1:+ 号连接
fn print_info<T: Display + Debug>(item: T) {
println!("{}", item);
println!("{:?}", item);
}
// 方式 2:where 子句(更清晰)
fn process<T, U>(t: T, u: U)
where
T: Display + Clone,
U: Debug + Clone,
{
println!("{}", t);
println!("{:?}", u);
}
// 方式 3:impl Trait(简洁)
fn print_item(item: impl Display) {
println!("{}", item);
}
错误 1:忘记实现必需的方法
trait Foo {
fn required_method(&self);
}
struct Bar;
impl Foo for Bar {
// ❌ 编译错误!没实现 required_method
}
编译器说:
not all trait items implemented, missing: `required_method`
正确做法:
impl Foo for Bar {
fn required_method(&self) {
println!("实现了!");
}
}
错误 2:Trait 对象大小问题
trait Animal {}
struct Dog;
impl Animal for Dog {}
fn get_animal() -> dyn Animal { // ❌ 编译错误!
Dog
}
编译器说:
the trait `Animal` cannot be made into an object
解释: Trait 对象是"动态大小类型",不能直接返回,要用指针包装。
正确做法:
fn get_animal() -> Box<dyn Animal> {
Box::new(Dog)
}
错误 3:孤儿规则限制
// ❌ 编译错误!不能为 Vec<String> 实现 Display
impl Display for Vec<String> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
编译器说:
only traits defined in the current crate can be implemented for arbitrary types
解释: 这是"孤儿规则"——你只能为自己的类型实现 Trait,或者为任意类型实现你自己定义的 Trait。
正确做法: 用新类型模式(Newtype Pattern)
struct MyVec(Vec<String>);
impl Display for MyVec {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self.)
}
}
// 泛型 - 编译时多态(快)
fn process<T: Drawable>(item: T) {
item.draw();
}
// Trait 对象 - 运行时多态(灵活但慢一点)
fn process(item: &dyn Drawable) {
item.draw();
}
选择原则:
trait Clone {
fn clone(&self) -> Self; // Self 是类型,self 是值
}
Self(大写):实现 Trait 的类型self(小写):方法接收者trait Foo {
fn foo(&self);
}
// Bar 继承 Foo,实现 Bar 必须先实现 Foo
trait Bar: Foo {
fn bar(&self);
}
trait Serializable {
fn to_json(&self) -> String;
}
struct User {
id: u32,
name: String,
email: String,
}
impl Serializable for User {
fn to_json(&self) -> String {
format!(
r#"{{"id": {}, "name": "{}", "email": "{}"}}"#,
self.id, self.name, self.email
)
}
}
struct Product {
sku: String,
price: f64,
}
impl Serializable for Product {
fn to_json(&self) -> String {
format!(
r#"{{"sku": "{}", "price": {}}}"#,
self.sku, self.price
)
}
}
// 泛型函数处理任何可序列化类型
fn save_to_file<T: Serializable>(item: &T, path: &str) {
let json = item.to_json();
println!("保存 {} 到 {}", json, path);
// 实际代码:std::fs::write(path, json)
}
fn main() {
let user = User {
id: ,
name: "张三".to_string(),
email: "zhangsan@example.com".to_string(),
};
let product = Product {
sku: "ABC123".to_string(),
price: 99.99,
};
save_to_file(&user, "user.json");
save_to_file(&product, "product.json");
}
trait Filter<T> {
fn apply(&self, items: &[T]) -> Vec<T>;
}
// 偶数过滤器
struct EvenFilter;
impl Filter<i32> for EvenFilter {
fn apply(&self, items: &[i32]) -> Vec<i32> {
items.iter().copied().filter(|x| x % == ).collect()
}
}
// 正数过滤器
struct PositiveFilter;
impl Filter<i32> for PositiveFilter {
fn apply(&self, items: &[i32]) -> Vec<i32> {
items.iter().copied().filter(|x| *x > ).collect()
}
}
fn process_with_filter<T: Clone, F: Filter<T>>(items: &[T], filter: F) -> Vec<T> {
filter.apply(items)
}
fn main() {
let numbers = vec![, , , , , -, -];
let evens = process_with_filter(&numbers, EvenFilter);
println!("偶数:{:?}", evens); // [2, 4, -2]
let positives = process_with_filter(&numbers, PositiveFilter);
println!("正数:{:?}", positives); // [1, 2, 3, 4, 5]
}
trait Command {
fn execute(&self);
fn undo(&self);
fn description(&self) -> &str;
}
struct TextEditor {
content: String,
}
impl TextEditor {
fn new() -> Self {
TextEditor { content: String::new() }
}
}
struct InsertText {
text: String,
}
impl Command for InsertText {
fn execute(&self) {
println!("插入文本:{}", self.text);
}
fn undo(&self) {
println!("撤销插入:{}", self.text);
}
fn description(&self) -> &str {
"插入文本"
}
}
struct DeleteText {
text: String,
}
impl Command for DeleteText {
fn execute(&self) {
println!("删除文本:{}", self.text);
}
fn undo(&self) {
println!("撤销删除:{}", self.text);
}
fn description(&self) -> &str {
"删除文本"
}
}
struct CommandHistory {
history: Vec<Box<dyn Command>>,
}
impl CommandHistory {
fn new() -> Self {
CommandHistory { history: Vec::new() }
}
fn add(&mut self, command: Box<dyn Command>) {
command.execute();
self.history.push(command);
}
fn undo_last(&mut self) {
if let Some(command) = self.history.pop() {
command.undo();
}
}
}
fn main() {
let mut history = CommandHistory::new();
history.add(Box::new(InsertText { text: "Hello".to_string() }));
history.add(Box::new(InsertText { text: " World".to_string() }));
history.add(Box::new(DeleteText { text: "World".to_string() }));
history.undo_last();
history.undo_last();
}

T: Trait 或 where 子句限制泛型类型dyn Trait 实现运行时多态,需要指针包装下篇预告: Rust 标准库有一堆常用 Trait,比如 Debug、Clone、Copy、From/Into……这些 Trait 天天用,但你可能不知道它们的门道!下篇我们逐个击破!