22·面向对象进阶

Trait Bound 约束

Trait Bound 约束

学习目标

  1. 掌握 trait bound 语法
  2. 使用 where 子句
  3. 理解多重约束
  4. 掌握条件实现

核心概念

基本 Trait Bound

use std::fmt::Display;

// impl Trait 语法(简写)
fn print_item(item: &impl Display) {
    println!("{}", item);
}

// Trait Bound 语法(完整)
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);
}

// 方式二:where 子句(更清晰)
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,
}

// 只有 T 实现了 Display 时才实现 show 方法
impl<T: Display> Wrapper<T> {
    fn show(&self) {
        println!("值: {}", self.value);
    }
}

// 只有 T 实现了 Clone 时才实现 duplicate
impl<T: Clone> Wrapper<T> {
    fn duplicate(&self) -> Self {
        Wrapper { value: self.value.clone() }
    }
}

// 只有 T 实现了 Debug + Display 时才实现 full_info
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 }
    }
}

// 只有可比较的 T 才有 cmp_display 方法
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));   // 6
    println!("{}", apply_to_3(add_one));  // 4
}

实践练习

练习 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 位置错误

// ❌ where 必须在 { 之前
fn foo<T>() where T: Display { }

// ✅
fn foo<T>() where T: Display { }

2. 遗漏约束

// ❌ 调用 .to_string() 需要 Display
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: Traitwhere 子句
impl Trait参数/返回值简写
impl<T: Trait> Struct<T>条件实现

练习编辑器

rust
Loading...