Menu
CoddyTech

带参数的特征

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

到目前为止,我们的 trait 方法都只接受 &self 作为参数。但 trait 方法也可以像普通方法一样接受额外的参数。这让它们在实际操作中实用得多。

定义 trait 时,你可以在方法签名中包含所需的任何参数:

trait Calculator {
    fn add(&self, a: i32, b: i32) -> i32;
    fn multiply(&self, a: i32, b: i32) -> i32;
}

这个 Calculator trait 要求实现两个方法,每个方法除了接受 &self 外,还要接受两个整数。任何实现此 trait 的类型都必须提供这两个操作,并使用完全相同的签名。

下面是结构体实现它的一种方式:

struct BasicCalc;

impl Calculator for BasicCalc {
    fn add(&self, a: i32, b: i32) -> i32 {
        a + b
    }
    
    fn multiply(&self, a: i32, b: i32) -> i32 {
        a * b
    }
}

现在你可以使用这些带参数的方法:

let calc = BasicCalc;
println!("{}", calc.add(5, 3));       // 8
println!("{}", calc.multiply(4, 7));  // 28

trait 定义了每个方法接受哪些参数,而实现定义了这些参数如何使用。这样,不同类型就能用各自的方式执行相同的操作:例如,LoggingCalc 可以在返回结果前打印每项操作。

challenge icon

挑战

简单

让我们来构建一个字符串处理工具包,让不同的处理器以各自的方式转换文本!你将创建一个 TextProcessor trait,其中的方法接受参数,然后为两种不同的处理器类型实现它。

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

  • processor.rs:定义一个公开的 TextProcessor trait,其中包含两个接受参数的方法:
    • repeat(&self, text: &str, times: u32) -> String:按指定次数重复给定文本
    • truncate(&self, text: &str, max_len: usize) -> String:将文本缩短到指定的最大长度
  • processors.rs:创建两个实现该 trait 的公开结构体:
    • SimpleProcessor:一个单元结构体,重复文本时在每次重复之间添加空格(例如,重复 3 次的 "Hi" 会变成 "Hi Hi Hi"),截断时则直接在最大长度处截断
    • FancyProcessor:一个单元结构体,重复文本时在每次重复之间添加 " * "(例如,重复 3 次的 "Hi" 会变成 "Hi * Hi * Hi");如果文本被缩短,则在末尾添加 "..."(仅当原文本长度超过 max_len 时)
  • main.rs:将各个模块组合起来,并演示相同的 trait 方法如何根据所用的处理器产生不同结果。

在主文件中,创建这两种处理器并使用输入来测试它们。你会收到三项输入:文本字符串、重复次数和最大长度。

打印四行,展示每种处理器的行为:

Simple repeat: {result}
Simple truncate: {result}
Fancy repeat: {result}
Fancy truncate: {result}

例如,输入 Hello、3 和 4 时:

Simple repeat: Hello Hello Hello
Simple truncate: Hell
Fancy repeat: Hello * Hello * Hello
Fancy truncate: Hell...

请注意,这两种处理器都遵循相同的 TextProcessor 契约,但各自以独特的方式转换文本。trait 定义了方法接受什么参数,而具体实现则决定如何使用这些参数!

你会收到三项输入:要处理的文本、重复次数(解析为 u32)以及截断的最大长度(解析为 usize)。

亲手试试

mod processor;
mod processors;

use processor::TextProcessor;
use processors::{SimpleProcessor, FancyProcessor};

fn main() {
    // 读取输入
    let mut text = String::new();
    std::io::stdin().read_line(&mut text).expect("Failed to read line");
    let text = text.trim();
    
    let mut times_input = String::new();
    std::io::stdin().read_line(&mut times_input).expect("Failed to read line");
    let times: u32 = times_input.trim().parse().expect("Failed to parse times");
    
    let mut max_len_input = String::new();
    std::io::stdin().read_line(&mut max_len_input).expect("Failed to read line");
    let max_len: usize = max_len_input.trim().parse().expect("Failed to parse max_len");
    
    // 创建处理器
    let simple = SimpleProcessor;
    let fancy = FancyProcessor;
    
    // TODO: 使用处理器转换文本并打印结果
    // 打印四行:
    // Simple repeat: {result}
    // Simple truncate: {result}
    // Fancy repeat: {result}
    // Fancy truncate: {result}
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Rust 在线编译器