Menu
CoddyTech

多个约束

本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 41 课,共 61 课。

有时,一个 trait 约束还不够。你可能需要一个既能打印又能提供摘要的泛型类型。Rust 允许你使用 + 语法来要求多个 trait。

下面介绍如何指定某个类型必须实现两个 trait:

use std::fmt::Display;

trait Summary {
    fn summarize(&self) -> String;
}

fn announce<T: Display + Summary>(item: T) {
    println!("Breaking news: {}", item);
    println!("Summary: {}", item.summarize());
}

这个约束 T: Display + Summary 表示“T 必须实现 Display 和 Summary”。在函数内部,你可以使用这两个 trait 的功能:用 {} 打印(来自 Display),以及调用 summarize()(来自 Summary)。

你可以根据需要链接任意多个特征:

fn process<T: Display + Summary + Clone>(item: T) {
    // 可以打印、生成摘要,还可以克隆
}

当你的函数依赖多种行为时,这种模式至关重要。与其接受任意类型并寄希望于它能正常工作,不如明确声明所需的具体功能,并让编译器在编译时强制检查。

challenge icon

挑战

简单

让我们构建一个产品检查系统,要求物品具备多种能力!你将创建一个泛型函数,它只接受同时实现自定义 trait 和标准 trait 的类型,以此展示 + 语法如何组合多个约束。

你将把代码分成两个文件:

  • product.rs:定义一个公开的 Inspectable trait,其中包含一个名为 inspect 的方法。该方法接收 &self,并返回包含检查详情的 String。然后创建一个公开的 Gadget 结构体,其中包含公开的 name(String)和 serial(u32)字段。你的 Gadget 应实现 Inspectable(返回 Inspecting: {name})和 std::fmt::Display(格式为 {name} (SN: {serial}))。最后,创建一个名为 full_report 的公开泛型函数,它接受任何同时实现了 Display 和 Inspectable 的类型 T。此函数应输出两行:第一行使用 {} 格式化器输出该物品,第二行输出调用 inspect() 的结果。
  • main.rs:引入你的 product 模块,并使用提供的输入创建一个 Gadget 实例。使用你的 gadget 调用 full_report,以展示它满足这两个 trait 的要求。

多个约束的优势在于,你的 full_report 函数可以使用这两个 trait 提供的能力,既能清晰地显示物品,又能获取检查详情,并且这些要求都能在编译时得到保证。

你的输出应同时显示格式化后的物品和检查结果:

{name} (SN: {serial})
Inspecting: {name}

例如,输入 Smartwatch 和 98765 时:

Smartwatch (SN: 98765)
Inspecting: Smartwatch

你将收到两个输入:设备名称和序列号(解析为 u32)。

亲手试试

mod product;

use product::{Gadget, full_report};

fn main() {
    // 读取输入
    let mut name = String::new();
    std::io::stdin().read_line(&mut name).expect("Failed to read line");
    let name = name.trim().to_string();
    
    let mut serial_input = String::new();
    std::io::stdin().read_line(&mut serial_input).expect("Failed to read line");
    let serial: u32 = serial_input.trim().parse().expect("Failed to parse serial");
    
    // TODO:用名称和序列号创建一个 Gadget 实例
    
    // TODO:用你创建的 Gadget 实例调用 full_report
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Rust 在线编译器