Menu
CoddyTech

泛型函数

本课属于 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)

泛型函数让你只需编写一次可复用的逻辑,就能将其应用于多种类型,从而减少代码重复,同时保证类型安全。

challenge icon

挑战

简单

一起来构建一个实用模块,其中包含可以处理任意类型的泛型函数!你将创建独立函数,展示泛型如何让代码灵活且可重复使用,而不受特定结构体的限制。

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

  • utils.rs:创建一组公开的泛型实用函数:
    • wrap_in_pair<T>:接收一个值,并返回一个包含该值两次的元组:(value, value)。这要求类型实现 Clone,因此要使用 <T: Clone>
    • swap<T, U>:接收两个类型可能不同的值,并以相反的顺序将它们作为元组 (U, T) 返回
  • main.rs:导入你的实用模块,并演示这些泛型函数如何处理不同类型。展示相同的函数定义如何轻松处理整数、浮点数和字符串。

在主文件中,通过以下方式演示你的实用函数:

  1. 对一个整数(第一个输入,解析为 i32)使用 wrap_in_pair,并打印两个元素
  2. 对一个字符串(第二个输入)使用 wrap_in_pair,并打印两个元素
  3. 对一个整数(第三个输入,解析为 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})
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Rust 在线编译器