泛型类型、特征和生命周期
每种编程语言都有有效处理重复的工具 的概念。在 Rust 中,一个这样的工具是 generics:抽象的替代项 具体类型或其他属性。我们可以表示泛型 或 它们如何与其他泛型相关联,而不知道它们的位置上会有什么 在编译和运行代码时。
函数可以采用某种泛型类型的参数,而不是具体类型
like 或 ,它们采用带有 unknown 的参数
values 对多个具体值运行相同的代码。事实上,我们已经
在第 6 章中使用了泛型,在第 8 章中使用了 和 ,在第 9 章中使用了泛型。在本章中,您将
探索如何使用泛型定义您自己的类型、函数和方法!i32
String
Option<T>
Vec<T>
HashMap<K, V>
Result<T, E>
首先,我们将回顾如何提取函数以减少代码重复。我们将 然后使用相同的技术从两个函数中创建一个泛型函数,这两个函数 仅在参数类型上有所不同。我们还将解释如何使用 struct 和 enum 定义中的泛型类型。
然后,您将学习如何使用 trait 以通用方式定义行为。你 可以将 trait 与泛型类型组合在一起,以约束泛型类型接受 仅那些具有特定行为的类型,而不是任何类型。
最后,我们将讨论生命周期:各种泛型,它们为 编译器 有关引用如何相互关联的信息。使用寿命允许 us 为编译器提供有关 borrowed values 的足够信息,以便它可以 确保引用在更多情况下有效,而不是没有 帮助。
通过提取函数删除重复项
泛型允许我们将特定类型替换为代表 multiple types 来删除代码重复。在深入研究泛型语法之前, 让我们首先看看如何以不涉及 泛型类型,方法是提取一个函数,该函数将特定值替换为 placeholder 表示多个值。然后我们将应用相同的 提取泛型函数的技术!通过查看如何识别 您可以提取到函数中的重复代码,您将开始识别 可以使用泛型的重复代码。
我们将从示例 10-1 中的短程序开始,它找到最大的 number 中。
文件名: src/main.rs
fn main() { let number_list = vec![34, 50, 25, 100, 65]; let mut largest = &number_list[0]; for number in &number_list { if number > largest { largest = number; } } println!("The largest number is {largest}"); assert_eq!(*largest, 100); }
我们在变量中存储一个整数列表并放置一个引用
添加到名为 .然后我们迭代
遍历列表中的所有数字,并且当前数字大于
存储在 中的数字将替换该变量中的引用。
但是,如果当前数字小于或等于看到的最大数字
到目前为止,变量没有改变,代码会移动到下一个数字
在列表中。在考虑了列表中的所有数字之后,应该
请参阅最大数字,在本例中为 100。number_list
largest
largest
largest
我们现在的任务是在两个不同的 数字。为此,我们可以选择复制示例 10-1 中的代码并使用 相同的 logic 在程序中的两个不同位置,如示例 10-2 所示。
文件名: src/main.rs
fn main() { let number_list = vec![34, 50, 25, 100, 65]; let mut largest = &number_list[0]; for number in &number_list { if number > largest { largest = number; } } println!("The largest number is {largest}"); let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8]; let mut largest = &number_list[0]; for number in &number_list { if number > largest { largest = number; } } println!("The largest number is {largest}"); }
尽管此代码有效,但复制代码既乏味又容易出错。我们还 当我们想要更改时,必须记住在多个地方更新代码 它。
为了消除这种重复,我们将通过定义一个 函数,该函数对作为参数传入的任何整数列表进行作。这 solution 使我们的代码更清晰,并让我们表达查找 abstract list 中的 largest 数字。
在示例 10-3 中,我们将找到最大数字的代码提取到
名为 .然后我们调用函数来找到最大的数字
在示例 10-2 的两个列表中。我们也可以在任何其他
我们将来可能拥有的值列表。largest
i32
文件名: src/main.rs
fn largest(list: &[i32]) -> &i32 { let mut largest = &list[0]; for item in list { if item > largest { largest = item; } } largest } fn main() { let number_list = vec![34, 50, 25, 100, 65]; let result = largest(&number_list); println!("The largest number is {result}"); assert_eq!(*result, 100); let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8]; let result = largest(&number_list); println!("The largest number is {result}"); assert_eq!(*result, 6000); }
该函数有一个名为 的参数,它表示任何
具体 Slice 的值。因此,
当我们调用函数时,代码将对我们传递的特定值运行
在。largest
list
i32
总之,以下是我们将代码从示例 10-2 更改为 示例 10-3:
- 识别重复代码。
- 将重复的代码提取到函数的主体中,并指定 函数签名中该代码的输入和返回值。
- 更新重复代码的两个实例以改为调用该函数。
接下来,我们将对泛型使用这些相同的步骤来减少代码重复。在
与 Function Body 可以对 Abstract 进行作的方式相同
的特定值,泛型允许代码对抽象类型进行作。list
例如,假设我们有两个函数:一个用于查找
Slice 的值,以及一个在 Values 切片中查找最大项的 Slice 值。我们将如何消除这种重复?让我们来了解一下!i32
char
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准