0Pricing
Learn Rust Coding · 课时

在 Rust 中编写泛型代码

学习编写适用于多种类型的函数和数据结构,在不牺牲类型安全的情况下提升代码复用性。

在 Rust 中编写泛型代码 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 1 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 3 节课。

为什么要编写泛型代码?

假设您需要一个函数来找出列表中最大的项。如果您需要它处理数字、字符,之后还要处理自定义对象,该怎么办?

没有泛型,您需要为每种类型分别编写一个函数,这会产生大量重复代码。这正是泛型发挥作用的地方!

介绍泛型

泛型让您能够编写适用于多种类型的代码,而不必重复编写相同内容。它是一种编写灵活且可复用的函数或数据结构的方式。

您可以把它想象成一个能够适应不同材料的蓝图。

您的第一个泛型函数

要让函数成为泛型函数,请在函数名称后面的尖括号 <> 中声明类型参数。常见的类型参数名称是 T(表示 Type,即类型)。

现在,这个 print_anything 函数可以打印任何类型的值了!

fn print_anything<T>(item: T) {
    println!("The item is: {}", item);
}

pub fn main() {
    print_anything(5);
    print_anything("hello");
    print_anything(true);
}

解释类型参数

fn print_anything<T>(item: T) 中的 <T> 表示 T 是类型的占位符。当您使用 i32 调用该函数时,T 就会变为 i32。

  • 类型参数:泛型类型通常使用大写字母命名,例如 T、U、V。
  • 灵活性:编译器会在编译时推断出具体类型。

添加行为:trait bound

有时,您的泛型函数要求其类型参数 T 具备特定行为。例如,如果您想比较两个 T,那么 T 必须是可比较的。

我们可以添加 trait bound 来指定这些要求。这里,T: PartialOrd + Copy 表示 T 必须实现 PartialOrd(用于比较的部分排序)和 Copy trait。

fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
    let mut largest = list[0];
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    largest
}

pub fn main() {
    let number_list = vec![34, 50, 25, 100, 65];
    println!("Largest number: {}", largest(&number_list));

    let char_list = vec!['y', 'm', 'a', 'q'];
    println!("Largest char: {}", largest(&char_list));
}

多个 trait bound 的语法

您可以使用 + 语法为泛型类型要求多个 trait,例如 T: TraitA + TraitB。

对于复杂的 bound,还可以在函数签名后使用 where 子句,这样可以让签名更简洁:

fn some_function<T, U>(t: T, u: U) -> i32 where T: Display + Clone, U: Clone + Debug { /* ... */ }

泛型结构体

与函数一样,您也可以让结构体接受一个或多个类型参数作为泛型。这样,数据结构就能存储任意指定类型的数据。

Point<T> 结构体可以存储任意类型 T 的坐标(例如 i32、f64)。

struct Point<T> {
    x: T,
    y: T,
}

pub fn main() {
    let integer_point = Point {
        x: 5,
        y: 10
    };
    let float_point = Point {
        x: 1.0,
        y: 4.0
    };

    println!("Int Point: ({}, {})", 
             integer_point.x, integer_point.y);
    println!("Float Point: ({}, {})", 
             float_point.x, float_point.y);
}

为泛型结构体实现方法

为泛型结构体实现方法时,需要在 impl 后指定泛型类型参数。

如果某个方法特别需要泛型类型具备某种行为,您还可以为该方法添加 trait bound。

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

pub fn main() {
    let p = Point {
        x: 5,
        y: 10
    };
    println!("p.x = {}", p.x());
}

泛型与性能

Rust 的优势之一是泛型属于零成本抽象。这意味着使用泛型不会带来运行时性能损失。

Rust 通过单态化实现这一点:在编译时,编译器会针对泛型代码所使用的每种具体类型生成专门的版本。因此,largest<i32> 和 largest<char> 会变成两个不同且经过优化的函数。

检验您的知识

以下关于 Rust 泛型的说法,哪些是正确的?

回顾:泛型的力量

在本课中,您学习了在 Rust 中编写泛型代码的基础知识:

  • 泛型是什么:一种编写灵活、可复用代码的方式。
  • 泛型函数:使用 <T> 表示类型参数。
  • trait bound:使用 T: Trait 指定所需行为。
  • 泛型结构体:创建能够存储泛型类型的数据结构。
  • 零成本:Rust 会将泛型编译为具体代码,确保不会产生运行时损失。

泛型是符合 Rust 惯用风格的代码的基石,能够实现强大且类型安全的抽象!

常见问题解答

「在 Rust 中编写泛型代码」课时是免费的吗?

是的 — 「在 Rust 中编写泛型代码」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 3 节课。

「在 Rust 中编写泛型代码」这节课中我会学到什么?

学习编写适用于多种类型的函数和数据结构,在不牺牲类型安全的情况下提升代码复用性。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Learn Rust Coding 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 3 节。

「在 Rust 中编写泛型代码」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Learn Rust Coding 课中编写并运行代码吗?

能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 在 Rust 中编写泛型代码
  2. 定义和实现 trait
  3. 高级 trait 用法:关联类型
← 返回 Learn Rust Coding