带参数的特征
本课属于 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 可以在返回结果前打印每项操作。
挑战
简单让我们来构建一个字符串处理工具包,让不同的处理器以各自的方式转换文本!你将创建一个 TextProcessor trait,其中的方法接受参数,然后为两种不同的处理器类型实现它。
你将把代码分成三个文件:
processor.rs:定义一个公开的TextProcessortrait,其中包含两个接受参数的方法: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}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器