泛型类型、特征和生命周期
每种编程语言都有有效处理重复的工具 的概念。在 Rust 中,一个这样的工具是 generics:抽象的替代项 具体类型或其他属性。我们可以表示泛型 或 它们如何与其他泛型相关联,而不知道它们的位置上会有什么 在编译和运行代码时。
函数可以采用某种泛型类型的参数,而不是具体类型
喜欢i32
或String
,它们采用带有 unknown 的参数
values 对多个具体值运行相同的代码。事实上,我们已经
在第 6 章中使用了泛型Option<T>
,在第 8 章中,使用Vec<T>
和HashMap<K, V>
,在第 9 章中,使用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); }
示例 10-1:在 列表中查找最大数字 数字
我们在变量number_list
并放置一个引用
添加到名为largest
.然后我们迭代
遍历列表中的所有数字,并且当前数字大于
存储在largest
,我们将替换该变量中的引用。
但是,如果当前数字小于或等于看到的最大数字
到目前为止,变量没有改变,代码会移动到下一个数字
在列表中。考虑了列表中的所有数字后,largest
应该
请参阅最大数字,在本例中为 100。
我们现在的任务是在两个不同的 数字。为此,我们可以选择复制示例 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}"); }
示例 10-2:在两个数字列表中查找最大数字的代码
尽管此代码有效,但复制代码既乏味又容易出错。我们还 当我们想要更改时,必须记住在多个地方更新代码 它。
为了消除这种重复,我们将通过定义一个 函数,该函数对作为参数传入的任何整数列表进行作。这 solution 使我们的代码更清晰,并让我们表达查找 abstract list 中的 largest 数字。
在示例 10-3 中,我们将找到最大数字的代码提取到
名为largest
.然后我们调用函数来找到最大的数字
在示例 10-2 的两个列表中。我们也可以在任何其他
列表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); }
示例 10-3:用于查找最大数字的抽象代码 分为两个列表
这largest
函数有一个名为list
,它表示任何
混凝土切片i32
值。因此,
当我们调用函数时,代码将对我们传递的特定值运行
在。
总之,以下是我们将代码从示例 10-2 更改为 示例 10-3:
- 识别重复代码。
- 将重复的代码提取到函数的主体中,并指定 函数签名中该代码的输入和返回值。
- 更新重复代码的两个实例以改为调用该函数。
接下来,我们将对泛型使用这些相同的步骤来减少代码重复。在
函数体可以对抽象进行作的方式相同list
相反
的特定值,泛型允许代码对抽象类型进行作。
例如,假设我们有两个函数:一个用于查找
的切片i32
值,另一个在 slice 中查找最大项的char
值。我们将如何消除这种重复?让我们来了解一下!
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准