泛型方法
本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 25 课,共 61 课。
泛型结构体可以保存任意类型,但如果没有与其数据交互的方法,它就不太实用。要为泛型结构体定义方法,你需要在 impl 块中使用一种特殊语法。
关键是在 impl 本身上声明泛型参数:
struct Wrapper<T> {
value: T,
}
impl<T> Wrapper<T> {
fn get(&self) -> &T {
&self.value
}
}
注意 Wrapper<T> 前面的 impl<T>。这告诉 Rust,T 是整个实现块的泛型类型参数。如果没有这个声明,Rust 就会查找名为 T 的具体类型,但找不到它。
get 方法返回 &T:一个指向包装器所持有类型的引用。无论 T 是整数、字符串还是其他类型,这都能正常工作:
let num_wrapper = Wrapper { value: 100 };
let text_wrapper = Wrapper { value: "Rust" };
println!("{}", num_wrapper.get()); // 100
println!("{}", text_wrapper.get()); // Rust
同一个方法定义适用于两者,因为泛型 T 会在编译时适配每种具体类型。
挑战
简单让我们为你的泛型容器添加方法!你将构建一个 Box 结构体(不要与 Rust 标准库中的 Box 混淆),它可以容纳任意类型,并提供用于操作其内容的方法。
你将把代码分成两个文件:
mybox.rs:定义一个名为MyBox<T>的公共泛型结构体,其中包含一个类型为T的私有字段contents。为这个结构体实现以下方法:- 一个
new关联函数,用给定的值创建一个新的MyBox - 一个
peek方法,返回对内容的引用(使用&self) - 一个
replace方法,接收一个新值并替换当前内容(使用&mut self)
- 一个
main.rs:引入你的模块,并演示泛型方法如何处理不同类型。你将创建多个盒子,查看它们的内容,并替换其中的值,以展示这些方法的效果。
请记住,在泛型结构体上实现方法时的关键语法:你需要在 MyBox<T> 前写上 impl<T>,告诉 Rust,T 是整个实现代码块的泛型参数。
在主文件中,通过以下操作演示你的 MyBox:
- 用一个整数创建一个盒子(第一个输入,解析为
i32) - 查看其中的内容并打印该值
- 用一个新整数替换其中的内容(第二个输入,解析为
i32) - 再次查看内容,以显示更新后的值
- 用一个字符串创建第二个盒子(第三个输入)
- 查看字符串盒子中的内容
你的输出应遵循以下格式:
Integer box contains: {value}
After replace: {value}
String box contains: {value}例如,输入 10、25 和 Rust 时:
Integer box contains: 10
After replace: 25
String box contains: Rust你将收到三个输入:一个初始整数、一个用于替换的整数,以及一个字符串值。
亲手试试
mod mybox;
use mybox::MyBox;
fn main() {
// 读取输入
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let initial_int: i32 = input1.trim().parse().expect("Invalid integer");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let replacement_int: i32 = input2.trim().parse().expect("Invalid integer");
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let string_value = input3.trim().to_string();
// TODO: 用初始整数创建一个 MyBox
// TODO: 查看其中的内容并打印:"Integer box contains: {value}"
// TODO: 用替换用的整数替换其中的内容
// TODO: 再次查看并打印:"After replace: {value}"
// TODO: 用字符串值创建第二个 MyBox
// TODO: 查看字符串盒子并打印:"String box contains: {value}"
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器