Trait Bound 约束
学习目标
- 掌握 trait bound 语法
- 使用
where 子句
- 理解多重约束
- 掌握条件实现
核心概念
基本 Trait Bound
use std::fmt::Display;
fn print_item(item: &impl Display) {
println!("{}", item);
}
fn print_item<T: Display>(item: &T) {
println!("{}", item);
}
多重约束
use std::fmt::{Debug, Display};
fn print_debug_display<T: Debug + Display>(item: &T) {
println!("Debug: {:?}", item);
println!("Display: {}", item);
}
fn print_debug_display<T>(item: &T)
where
T: Debug + Display,
{
println!("Debug: {:?}", item);
println!("Display: {}", item);
}
返回值约束
fn create_displayable() -> impl Display {
42
}
条件实现
struct Wrapper<T> {
value: T,
}
impl<T: Display> Wrapper<T> {
fn show(&self) {
println!("值: {}", self.value);
}
}
impl<T: Clone> Wrapper<T> {
fn duplicate(&self) -> Self {
Wrapper { value: self.value.clone() }
}
}
impl<T> Wrapper<T>
where
T: Debug + Display + Clone,
{
fn full_info(&self) {
println!("Display: {}", self.value);
println!("Debug: {:?}", self.value);
}
}
使用 trait bound 修复之前的代码
use std::fmt::Display;
struct Pair<T> {
first: T,
second: T,
}
impl<T> Pair<T> {
fn new(first: T, second: T) -> Self {
Pair { first, second }
}
}
impl<T: Display + PartialOrd> Pair<T> {
fn cmp_display(&self) {
if self.first >= self.second {
println!("较大的是: {}", self.first);
} else {
println!("较大的是: {}", self.second);
}
}
}
trait bound 与闭包
fn apply_to_3<F>(f: F) -> i32
where
F: Fn(i32) -> i32,
{
f(3)
}
fn main() {
let double = |x| x * 2;
let add_one = |x| x + 1;
println!("{}", apply_to_3(double));
println!("{}", apply_to_3(add_one));
}
实践练习
练习 1:可序列化
trait Serializable {
fn serialize(&self) -> String;
}
#[derive(Debug)]
struct User {
name: String,
age: u32,
}
impl Serializable for User {
fn serialize(&self) -> String {
format!("{{\"name\":\"{}\",\"age\":{}}}", self.name, self.age)
}
}
fn save<T: Serializable + std::fmt::Debug>(item: &T) {
let data = item.serialize();
println!("保存: {}", data);
println!("调试: {:?}", item);
}
fn main() {
let user = User { name: String::from("Alice"), age: 30 };
save(&user);
}
练习 2:条件打印
trait Printable {
fn format(&self) -> String;
}
impl Printable for i32 {
fn format(&self) -> String { format!("int:{}", self) }
}
impl Printable for String {
fn format(&self) -> String { format!("str:{}", self) }
}
fn print_items<T: Printable>(items: &[T]) {
for item in items {
println!("{}", item.format());
}
}
fn main() {
let numbers = vec![1, 2, 3];
print_items(&numbers);
}
常见错误
1. where 位置错误
fn foo<T>() where T: Display { }
fn foo<T>() where T: Display { }
2. 遗漏约束
fn to_string<T>(val: T) -> String {
val.to_string()
}
fn to_string<T: Display>(val: T) -> String {
val.to_string()
}
小结
| 语法 | 用途 |
|---|
T: Trait | 单个约束 |
T: Trait1 + Trait2 | 多重约束 |
where T: Trait | where 子句 |
impl Trait | 参数/返回值简写 |
impl<T: Trait> Struct<T> | 条件实现 |