Menu
CoddyTech

泛型方法

本课属于 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 会在编译时适配每种具体类型。

challenge icon

挑战

简单

让我们为你的泛型容器添加方法!你将构建一个 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:

  1. 用一个整数创建一个盒子(第一个输入,解析为 i32)
  2. 查看其中的内容并打印该值
  3. 用一个新整数替换其中的内容(第二个输入,解析为 i32)
  4. 再次查看内容,以显示更新后的值
  5. 用一个字符串创建第二个盒子(第三个输入)
  6. 查看字符串盒子中的内容

你的输出应遵循以下格式:

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}"
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Rust 在线编译器