首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Rust学习】23_泛型类型、特征和生命周期

【Rust学习】23_泛型类型、特征和生命周期

原创
作者头像
思索
发布2025-01-13 08:56:35
发布2025-01-13 08:56:35
2830
举报
文章被收录于专栏:Rust入门笔记Rust入门笔记

在编程中,处理概念重复是一个常见问题,不同的编程语言提供了不同的工具来解决这个问题。在 Rust 中,泛型就是这样一种工具,它允许我们编写与具体类型无关的代码,从而避免重复。

泛型是具体类型或其他属性的抽象替代品,它们使得我们能够编写出更加通用的函数和数据结构。通过使用泛型,我们可以定义行为,这些行为不仅仅局限于特定的类型,而是可以适用于多种类型。这种抽象让我们在编译时不必知道具体的类型是什么,泛型的真实类型将在代码被实例化时确定。

函数确实可以接收泛型类型的参数,而不是像 i32String 这样的具体类型。这种方式允许函数对多种不同的具体类型使用相同的代码逻辑,就像它们能够处理带有未知值的参数一样。实际上,我们已经在前面的章节中见识了泛型的实际应用:

  • 我们使用了 Option<T>,它是一个用于可能缺失值的类型。
  • 我们使用了 Vec<T>,这是一个存储同一类型多个值的动态数组,以及 HashMap<K, V>,这是一个基于键值对存储数据的集合。
  • 我们使用了 Result<T, E>,它用来表示操作可能成功(返回 T)或失败(返回 E)。

在本章中,您将深入了解如何利用泛型来定义自己的类型、函数和方法。使用泛型,您可以编写出更加灵活和通用的代码,这些代码能够适应不同的数据类型,而不需要为每种类型编写重复的逻辑。

首先,我们将回顾如何通过提取函数来减少代码中的重复部分。接着,我们会应用类似的技术,将两个只在参数类型上有所区别的函数合并为一个泛型函数。此外,我们还将探讨如何在结构体(struct)和枚举(enum)的定义中运用泛型类型。这样,您将能够创建出更加通用和灵活的代码结构。

接下来,您将掌握如何利用 trait 来以一种通用的方式定义行为。通过将 trait 与泛型结合,您可以限制泛型类型只能接受实现了特定行为的类型,而不仅仅是任何随机类型。这种结合使用 trait 和泛型的方法,让您能够编写出更加灵活且具有强类型检查的代码。

最后,我们将探讨生命周期(Lifetimes)的概念:这是 Rust 中的一种泛型,它向编译器提供了关于引用之间如何相互关联的详细信息。通过生命周期,编译器能够获得足够的信息来判断借用的值在何种情况下是有效的,从而确保引用的有效性,而无需程序员显式地提供额外的帮助。

通过提取函数删除重复项

泛型使我们能够通过替换特定类型为一个代表多种类型的占位符来消除代码重复。在深入探讨泛型语法之前,我们先来看一个不涉及泛型的情况,如何通过提取函数来删除重复代码,这个函数将特定值替换为一个能代表多个值的占位符。接着,我们将应用相同的技术来提取泛型函数。通过学习如何识别可以提取到函数中的重复代码,您将开始学会识别那些可以通过泛型来消除的重复代码。

我们将从下面的一个简短程序着手,该程序旨在从列表中找出最大的数字。

代码语言:rust
复制
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);
}

我们首先将一个整数列表存储在变量 number_list 中,并将列表中的第一个数字的引用赋给名为 largest 的变量。接着,我们遍历列表中的每一个数字,如果发现当前数字大于 largest 变量中存储的数字,我们就更新 largest 以引用这个新发现的较大数字。如果当前数字小于或等于当前 largest 中的数字,我们则不作任何改变,并继续检查列表中的下一个数字。经过对列表中所有数字的检查后,largest 将引用列表中的最大数字,在本例中即为 100。

我们现在的任务是在两个不同的数字列表中找到最大的数字。为此,我们可以选择复制上方示例中的代码,并在程序中的两个不同位置使用相同的逻辑,如下所示:

代码语言:rust
复制
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}");
}

尽管这段代码能够正常工作,但复制粘贴代码不仅乏味,而且容易引入错误。此外,每当我们想要修改代码时,都需要在多个地方进行更新,这增加了维护的难度。

为了消除这种重复性,我们将定义一个函数,这个函数能够抽象地处理作为参数传入的任何整数列表。通过这种方式,我们不仅使代码更加简洁清晰,而且还能够以一种更抽象的方式表达在列表中查找最大数字的概念。这样的解决方案有助于减少代码冗余,并提升代码的可维护性和可重用性。

在下面的示例中,我们将寻找最大数字的代码抽象并提取到一个名为 largest 的函数中。接着,我们利用这个函数来确定上面代码中两个列表的最大数字。此外,这个函数也适用于我们未来可能遇到的任何包含 i32 值的列表,使其成为一个通用的解决方案。

代码语言:rust
复制
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);
}

largest 函数接受一个名为 list 的参数,这个参数可以是任何 i32 类型值的切片,代表我们可能传递给函数的具体列表。因此,当我们调用这个函数时,它将针对我们传入的具体数值执行相应的操作。

总结来说,以下是我们优化的步骤:

  1. 提取重复代码:识别出示例中用于寻找最大数字的重复逻辑,并将其提取出来。
  2. 定义泛型函数:将重复代码提取到函数体中,并在函数签名中指定该代码的输入和返回值。
  3. 调用函数:更新重复代码的两个实例以改为调用该函数。

接下来,我们将采用类似的方法来利用泛型减少代码重复。正如函数可以操作一个抽象的list而不是具体的值,泛型允许我们的代码对抽象类型进行操作,而不是仅限于特定的类型。这样,我们就能够编写出更加通用和可重用的代码。

假设我们有两个函数,一个用来找出 i32 值的切片中的最大项,另一个用来找出 char 值的切片中的最大项。面对这种情况,我们该如何消除代码中的重复部分呢?让我们来探讨一下解决方案。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 通过提取函数删除重复项
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档