泛型结构体
本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 24 课,共 61 课。
到目前为止,你创建的每个结构体都有特定的具体类型字段。Pet 有一个 String 类型的名称,Rectangle 有 f64 类型的尺寸。但如果你想创建一个可以存放任意类型数据的结构体呢?
这就是泛型的用武之地。泛型能让你编写灵活、可复用的代码,使其适用于多种类型。你不必硬编码特定类型,而是使用一个占位符,通常是 T,在使用结构体时再将其替换为具体类型。
这是一个简单的包装器结构体,可以保存任意类型:
struct Wrapper<T> {
value: T,
}
结构体名称后的 <T> 声明了一个泛型类型参数。在结构体内部,T 代表你实际要使用的类型。创建实例时,Rust 会推断具体类型:
let int_wrapper = Wrapper { value: 42 }; // T 是 i32
let float_wrapper = Wrapper { value: 3.14 }; // T 是 f64
let text_wrapper = Wrapper { value: "hello" }; // T 是 &str
它们分别是不同的具体类型:Wrapper<i32>、Wrapper<f64> 和 Wrapper<&str>,但它们都使用相同的结构体定义。这样就不需要编写功能基本相同的 IntWrapper、FloatWrapper 和 StringWrapper 结构体了。
字母 T 只是一个约定(是“类型”的缩写)。你可以使用任何有效的标识符,但在 Rust 和大多数其他支持泛型的语言中,T 是标准写法。
挑战
简单让我们构建一个可以容纳任意类型值的泛型容器!你将创建一个 Container 结构体,展示泛型如何让代码灵活且可复用。
你将把代码分成两个文件:
container.rs:定义一个名为Container<T>的公有泛型结构体,其中包含一个类型为T的公有字段item。这个容器可以容纳任意类型的值:整数、浮点数、字符串或其他任何类型。main.rs:引入容器模块,并通过创建可容纳不同数据类型的容器来展示它的灵活性。你将创建三个容器,并显示每个容器中保存的内容。
在主文件中,创建以下容器:
- 一个保存整数值的容器(第一个输入,解析为
i32) - 一个保存浮点数值的容器(第二个输入,解析为
f64) - 一个保存字符串的容器(第三个输入,保留为
String)
输出应按以下格式显示每个容器中的内容:
Integer container: {value}
Float container: {value}
String container: {value}例如,输入 42、3.14 和 hello 时:
Integer container: 42
Float container: 3.14
String container: hello注意,同一个 Container<T> 定义适用于这三种不同类型,这就是泛型的强大之处!
你将收到三个输入:一个整数值、一个浮点数值和一个字符串值。
亲手试试
mod container;
use container::Container;
fn main() {
// 读取三个输入
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let int_value: i32 = input1.trim().parse().expect("Failed to parse integer");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let float_value: f64 = input2.trim().parse().expect("Failed to parse float");
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: 使用 Container<T> 创建三个容器
// 1. 存放 int_value 的整数容器
// 2. 存放 float_value 的浮点数容器
// 3. 存放 string_value 的字符串容器
// TODO: 按要求的格式输出每个容器的内容
// Integer container: {value}
// Float container: {value}
// String container: {value}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器