trait是Rust的抽象机制,类似其他语言的接口(interface),但更强大。它定义了类型可以实现的行为,配合泛型的trait bound,让你写出既灵活又安全的代码。
学习目标:定义和实现trait、默认方法、trait bound、trait对象、运算符重载
use std::fmt;
// 定义trait
trait Summary {
fn summarize_author(&self) -> String;
// 默认实现
fn summarize(&self) -> String {
format!("(阅读更多来自{}的内容...)", self.summarize_author())
}
}
struct Article {
title: String,
author: String,
content: String,
}
struct Tweet {
username: String,
content: String,
}
// 为类型实现trait
impl Summary for Article {
fn summarize_author(&self) -> String {
self.author.clone()
}
// 覆盖默认实现
fn summarize(&self) -> String {
format!("{},作者{}", self.title, self.author)
}
}
impl Summary for Tweet {
fn summarize_author(&self) -> String {
format!("@{}", self.username)
}
// 使用默认的summarize
}
fn main() {
let article = Article {
title: "Rust 1.95发布".to_string(),
author: "Rust团队".to_string(),
content: "新版本带来了...".to_string(),
};
println!("{}", article.summarize());
let tweet = Tweet {
username: "rustlang".to_string(),
content: "Rust 1.95 is out!".to_string(),
};
println!("{}", tweet.summarize());
}
✅ 验证通过
trait Draw {
fn draw(&self);
}
struct Circle { radius: f64 }
struct Rectangle { width: f64, height: f64 }
struct Triangle { base: f64, height: f64 }
impl Draw for Circle {
fn draw(&self) {
println!("⭕ 圆 (半径={})", self.radius);
}
}
impl Draw for Rectangle {
fn draw(&self) {
println!("▬ 矩形 ({}×{})", self.width, self.height);
}
}
impl Draw for Triangle {
fn draw(&self) {
println!("△ 三角形 (底={}, 高={})", self.base, self.height);
}
}
// 方式1: impl Trait语法(静态分发)
fn draw_shape(shape: &impl Draw) {
shape.draw();
}
// 等价写法(泛型 + trait bound)
fn draw_shape_generic(shape: &T) {
shape.draw();
}
// 多个trait bound
fn draw_and_debug(shape: &(impl Draw + std::fmt::Debug)) {
println!("调试: {:?}", shape);
shape.draw();
}
// 方式2: trait对象(动态分发)
fn draw_all(shapes: &[Box]) {
for shape in shapes {
shape.draw();
}
}
fn main() {
let circle = Circle { radius: 5.0 };
let rect = Rectangle { width: 3.0, height: 4.0 };
draw_shape(&circle);
draw_shape(&rect);
// 异构集合 —— 只有trait对象能做到
let shapes: Vec> = vec![
Box::new(Circle { radius: 2.0 }),
Box::new(Rectangle { width: 3.0, height: 4.0 }),
Box::new(Triangle { base: 5.0, height: 3.0 }),
];
println!("\n绘制所有图形:");
draw_all(&shapes);
}
✅ 验证通过
use std::fmt::Display;
// where子句 —— 更清晰的trait bound写法
fn longest_with_announcement<'a, T>(
x: &'a str,
y: &'a str,
ann: T,
) -> &'a str
where
T: Display,
{
println!("📢 公告: {}", ann);
if x.len() > y.len() { x } else { y }
}
// 条件实现
struct Pair {
x: T,
y: T,
}
impl Pair {
fn new(x: T, y: T) -> Self {
Pair { x, y }
}
}
// 只有T实现了Display + PartialOrd才能cmp_display
impl Pair {
fn cmp_display(&self) {
if self.x >= self.y {
println!("x >= y: {} >= {}", self.x, self.y);
} else {
println!("x < y: {} < {}", self.x, self.y);
}
}
}
// blanket implementation(覆盖实现)
// 标准库示例:impl ToString for T { ... }
// 任何实现了Display的类型都自动实现了ToString
fn main() {
let result = longest_with_announcement("hello", "hi there", "比较字符串");
println!("更长的: {}", result);
let pair = Pair::new(3.14, 2.71);
pair.cmp_display();
// ToString就是通过blanket impl从Display自动获得的
let s = 42.to_string(); // i32实现了Display → 自动有ToString
println!("数字转字符串: {}", s);
}
✅ 验证通过
use std::ops::{Add, Mul, Neg};
#[derive(Debug, Clone, Copy, PartialEq)]
struct Vec2 {
x: f64,
y: f64,
}
impl Vec2 {
fn new(x: f64, y: f64) -> Self {
Vec2 { x, y }
}
fn dot(&self, other: &Vec2) -> f64 {
self.x * other.x + self.y * other.y
}
fn magnitude(&self) -> f64 {
self.dot(self).sqrt()
}
fn normalize(&self) -> Self {
let mag = self.magnitude();
Vec2 { x: self.x / mag, y: self.y / mag }
}
}
impl Add for Vec2 {
type Output = Vec2;
fn add(self, rhs: Vec2) -> Vec2 {
Vec2 { x: self.x + rhs.x, y: self.y + rhs.y }
}
}
impl Mul for Vec2 {
type Output = Vec2;
fn mul(self, scalar: f64) -> Vec2 {
Vec2 { x: self.x * scalar, y: self.y * scalar }
}
}
impl Neg for Vec2 {
type Output = Vec2;
fn neg(self) -> Vec2 {
Vec2 { x: -self.x, y: -self.y }
}
}
impl std::fmt::Display for Vec2 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
fn main() {
let a = Vec2::new(3.0, 4.0);
let b = Vec2::new(1.0, 2.0);
println!("a = {}", a);
println!("b = {}", b);
println!("a + b = {}", a + b);
println!("a * 2 = {}", a * 2.0);
println!("-a = {}", -a);
println!("a·b = {}", a.dot(&b));
println!("|a| = {:.2}", a.magnitude());
println!("a归一化 = {}", a.normalize());
}
✅ 验证通过
use std::fmt;
// 插件trait
trait Plugin: fmt::Debug {
fn name(&self) -> &str;
fn version(&self) -> &str;
fn initialize(&mut self) -> Result<(), String>;
fn execute(&self, input: &str) -> String;
fn shutdown(&mut self) {}
}
// 日志插件
#[derive(Debug)]
struct LoggerPlugin {
initialized: bool,
log_count: usize,
}
impl LoggerPlugin {
fn new() -> Self {
LoggerPlugin { initialized: false, log_count: 0 }
}
}
impl Plugin for LoggerPlugin {
fn name(&self) -> &str { "Logger" }
fn version(&self) -> &str { "1.0.0" }
fn initialize(&mut self) -> Result<(), String> {
self.initialized = true;
Ok(())
}
fn execute(&self, input: &str) -> String {
format!("[LOG] {}", input)
}
fn shutdown(&mut self) {
println!("Logger插件关闭,共记录{}条日志", self.log_count);
}
}
// 转换插件
#[derive(Debug)]
struct UppercasePlugin {
initialized: bool,
}
impl UppercasePlugin {
fn new() -> Self {
UppercasePlugin { initialized: false }
}
}
impl Plugin for UppercasePlugin {
fn name(&self) -> &str { "Uppercase" }
fn version(&self) -> &str { "2.0.0" }
fn initialize(&mut self) -> Result<(), String> {
self.initialized = true;
Ok(())
}
fn execute(&self, input: &str) -> String {
input.to_uppercase()
}
}
// 插件管理器
struct PluginManager {
plugins: Vec<Box,
}
impl PluginManager {
fn new() -> Self {
PluginManager { plugins: Vec::new() }
}
fn register(&mut self, mut plugin: Box) -> Result<(), String> {
plugin.initialize()?;
println!("✅ 注册插件: {} v{}", plugin.name(), plugin.version());
self.plugins.push(plugin);
Ok(())
}
fn execute_all(&self, input: &str) -> Vec<String> {
self.plugins.iter()
.map(|p| {
let result = p.execute(input);
format!("[{}] {}", p.name(), result)
})
.collect()
}
fn list(&self) {
println!("已注册插件 ({}个):", self.plugins.len());
for p in &self.plugins {
println!(" - {} v{}", p.name(), p.version());
}
}
}
fn main() {
let mut manager = PluginManager::new();
manager.register(Box::new(LoggerPlugin::new())).unwrap();
manager.register(Box::new(UppercasePlugin::new())).unwrap();
manager.list();
let results = manager.execute_all("Hello, Rust!");
for result in results {
println!("{}", result);
}
}
✅ 验证通过
定义Describable trait,包含describe(&self) -> String方法。为i32、String、Vec<T>实现它。
定义Sortable trait,包含sort_key(&self) -> i64。实现一个通用排序函数sort_by_key<T: Sortable>(items: &mut [T])。
为Complex<f64>实现Add、Sub、Mul和Display trait。
🔒 下一课解锁:生命周期 —— 引用有效性的保证
use std::fmt;
// 关联类型
trait Container {
type Item;
fn get(&self, index: usize) -> Option<&Self::Item>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool { self.len() == 0 }
}
struct Array3 { data: [T; 3] }
impl Container for Array3 {
type Item = T;
fn get(&self, index: usize) -> Option<&T> { self.data.get(index) }
fn len(&self) -> usize { 3 }
}
// trait对象与动态分发
trait Drawable {
fn draw(&self);
fn area(&self) -> f64;
}
struct Circle { radius: f64 }
struct Square { side: f64 }
impl Drawable for Circle {
fn draw(&self) { println!("⭕ 圆 r={}", self.radius); }
fn area(&self) -> f64 { std::f64::consts::PI * self.radius * self.radius }
}
impl Drawable for Square {
fn draw(&self) { println!("⬛ 方 s={}", self.side); }
fn area(&self) -> f64 { self.side * self.side }
}
fn total_area(shapes: &[Box]) -> f64 {
shapes.iter().map(|s| s.area()).sum()
}
fn main() {
let arr = Array3 { data: [10, 20, 30] };
for i in 0..arr.len() {
println!("arr[{}] = {}", i, arr.get(i).unwrap());
}
let shapes: Vec> = vec![
Box::new(Circle { radius: 5.0 }),
Box::new(Square { side: 4.0 }),
];
for s in &shapes { s.draw(); }
println!("总面积: {:.2}", total_area(&shapes));
}
✅ 验证通过