泛型函数
本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 27 课,共 61 课。
泛型不仅限于结构体。你也可以编写适用于任意类型的独立函数。当你需要一个不属于特定结构体、但仍应保持灵活的实用函数时,这会很有用。
语法与之前看到的结构体类似。在函数名后面的尖括号中声明泛型参数,然后在参数和返回类型中使用它:
fn identity<T>(value: T) -> T {
value
}
这个 identity 函数接收任意类型的值,并原样返回。<T> 声明了泛型,value: T 将其作为参数接收,而 -> T 指定了返回类型。调用这个函数时,Rust 会推断出具体类型:
let num = identity(42); // T 是 i32
let text = identity("hello"); // T 是 &str
你也可以在函数中使用多个泛型参数,就像在结构体中一样:
fn make_pair<T, U>(first: T, second: U) -> (T, U) {
(first, second)
}
let pair = make_pair(10, "ten"); // 返回 (i32, &str)
泛型函数让你只需编写一次可复用的逻辑,就能将其应用于多种类型,从而减少代码重复,同时保证类型安全。
挑战
简单一起来构建一个实用模块,其中包含可以处理任意类型的泛型函数!你将创建独立函数,展示泛型如何让代码灵活且可重复使用,而不受特定结构体的限制。
你将把代码分成两个文件:
utils.rs:创建一组公开的泛型实用函数:wrap_in_pair<T>:接收一个值,并返回一个包含该值两次的元组:(value, value)。这要求类型实现Clone,因此要使用<T: Clone>swap<T, U>:接收两个类型可能不同的值,并以相反的顺序将它们作为元组(U, T)返回
main.rs:导入你的实用模块,并演示这些泛型函数如何处理不同类型。展示相同的函数定义如何轻松处理整数、浮点数和字符串。
在主文件中,通过以下方式演示你的实用函数:
- 对一个整数(第一个输入,解析为
i32)使用wrap_in_pair,并打印两个元素 - 对一个字符串(第二个输入)使用
wrap_in_pair,并打印两个元素 - 对一个整数(第三个输入,解析为
i32)和一个字符串(第四个输入)使用swap,然后打印交换后的结果
你的输出应遵循以下格式:
Pair of ints: ({value}, {value})
Pair of strings: ({value}, {value})
Swapped: ({string}, {int})例如,输入 5、hello、42 和 world 时:
Pair of ints: (5, 5)
Pair of strings: (hello, hello)
Swapped: (world, 42)注意,wrap_in_pair 对整数和字符串的处理方式完全相同,而 swap 可以处理两种完全不同的类型:这就是泛型函数的灵活性!
你将收到四个输入:一个整数、一个字符串、另一个整数和另一个字符串。
亲手试试
mod utils;
use std::io;
fn main() {
// 读取四个输入
let mut input1 = String::new();
io::stdin().read_line(&mut input1).expect("Failed to read line");
let num1: i32 = input1.trim().parse().expect("Invalid integer");
let mut input2 = String::new();
io::stdin().read_line(&mut input2).expect("Failed to read line");
let str1 = input2.trim().to_string();
let mut input3 = String::new();
io::stdin().read_line(&mut input3).expect("Failed to read line");
let num2: i32 = input3.trim().parse().expect("Invalid integer");
let mut input4 = String::new();
io::stdin().read_line(&mut input4).expect("Failed to read line");
let str2 = input4.trim().to_string();
// TODO: 用 wrap_in_pair 处理 num1,并打印结果
// 格式:Pair of ints: ({value}, {value})
// TODO: 用 wrap_in_pair 处理 str1,并打印结果
// 格式:Pair of strings: ({value}, {value})
// TODO: 用 swap 交换 num2 和 str2,然后打印交换后的结果
// 格式:Swapped: ({string}, {int})
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Rust 在线编译器