Rust之泛型、特性和生命期(一):基本概念

开发环境

  • Windows 10
  • Rust 1.69.0

 

  • VS Code 1.77.3

 项目工程

这里继续沿用上次工程rust-demo

泛型、特性和生命期 

每种编程语言都有有效处理概念重复的工具。在Rust中,一个这样的工具就是泛型:具体类型或其他属性的抽象替身。我们可以表达泛型的行为或它们与其他泛型的关系,而不知道在编译和运行代码时它们的位置会是什么。

函数可以接受一些泛型的参数,而不是像i32String这样的具体类型,就像函数接受未知值的参数一样,对多个具体值运行相同的代码。事实上,我们已经在之前的章节的Option<T>、向量Vec<T>HashMap<K, V>,以及Result<T, E>中使用了泛型。在这一章中,你将探索如何用泛型定义你自己的类型、函数和方法!

首先,我们将回顾如何提取一个函数以减少代码的重复。然后,我们将使用同样的技术,从两个仅在参数类型上有差异的函数中提取出一个泛型函数。我们还将解释如何在结构和枚举的定义中使用泛型。

然后你将学习如何使用特质以通用方式定义行为。你可以将特质与泛型结合起来,约束泛型只接受那些具有特定行为的类型,而不是任何类型。

最后,我们将讨论生命期:各种泛型,给编译器提供关于引用如何相互关联的信息。生命期允许我们给编译器提供足够的关于借用值的信息,这样它就可以确保引用在更多的情况下是有效的,而不需要我们的帮助。

通过提取一个函数来消除重复

泛型允许我们用一个代表多种类型的占位符来替换特定的类型,以消除代码的重复。在深入研究泛型语法之前,让我们先看看如何通过提取一个用代表多个值的占位符替换特定值的函数,以一种不涉及泛型类型的方式来消除重复。然后,我们将应用同样的技术来提取一个泛型的函数! 通过研究如何识别可以提取到一个函数中的重复代码,你将开始识别可以使用泛型的重复代码。

我们从示例1中的短程序开始,它可以找到一个数组种的最大的数字。

文件名: 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);
}

示例1 寻找数组中的最大数字

我们在变量number_list中存储一个数组,并将数组中第一个数字的引用放在一个名为maximum的变量中。然后我们遍历数组中的所有数字,如果当前数字大于存储在largest中的数字,则替换该变量中的引用。然而,如果当前的数字小于或等于到目前为止所看到的最大的数字,变量就不会改变,代码就会转到数组中的下一个数字。在考虑了数组中的所有数字后,largest应该指的是最大的数字,在本例中是100。

我们现在的任务是在两个不同的数组中找出最大的数字。为此,我们可以选择复制清单10-1中的代码,在程序中的两个不同地方使用相同的逻辑,如示例2所示。

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);
}

示例2:寻找两个数组中最大数字的代码

虽然这段代码是有效的,但重复代码是繁琐的,而且容易出错。当我们想改变代码时,我们还得记住在多个地方更新代码。

为了消除这种重复,我们将通过定义一个函数来创建一个抽象,该函数可以对参数中传递的任何整数的数组进行操作。这个解决方案使我们的代码更加清晰,并使我们能够抽象地表达寻找数组中最大数字的概念。

在示例3中,我们将寻找最大数字的代码提取到一个名为maximum的函数中。然后,我们调用这个函数来寻找示例2中两个数组中的最大数字。我们也可以在将来可能出现的任何其他i32值的数组中使用这个函数。

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);             // 调用函数largest
    println!("The largest number is {}", result);

    let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8];
 
    let result = largest(&number_list);            // 调用函数largest
    println!("The largest number is {}", result);
}

示例3:查找两个数组中最大数字的抽象代码

最大的函数有一个叫做list的参数,它代表了我们可能传入函数的任何具体的i32切片。因此,当我们调用该函数时,代码在我们传入的具体数值上运行。

综上所述,以下是我们将代码从示例2改为示例3的步骤:

  • 识别重复的代码。
  • 将重复的代码提取到函数的主体中,并在函数签名中指定该代码的输入和返回值。
  • 更新两个重复代码的实例,以调用该函数代替。

接下来,我们将使用这些相同的步骤,用泛型来减少代码的重复。就像函数主体可以对抽象list而不是具体数值进行操作一样,泛型允许代码对抽象类型进行操作。

例如,假设我们有两个函数:一个是在i32值的切片中寻找最大的项目,一个是在char值的切片中寻找最大的项目。我们将如何消除这种重复呢?让我们拭目以待!

本章重点

  • 泛型的基本概念
  • 函数抽象:提取重复代码
  • 求取数组中的最大数方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/14394.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【世界读书日】2023年通信好书推荐

今天是世界读书日&#xff08;4月23日&#xff09;。按照老规矩&#xff0c;小编给大家推荐一些通信类的优秀书籍。 过去一年&#xff0c;通信行业的关注热点&#xff0c;主要是&#xff1a;5G-Advanced&#xff08;5.5G&#xff09;、算力网络、东数西算、6G、卫星互联网、智…

如何正确高效地学习android开发?

每一个能成为行业大佬的人&#xff0c;一定有自己独特的方法… 之所以能成为大佬&#xff0c;是因为他们会有自己独特的见解&#xff0c;在一次次的尝试中不断否定&#xff0c;然后一次次的确定&#xff0c;一个程序员想要精益求精&#xff0c;必须要有高效的学习方法和良好的…

历史上的今天大事件查询工具推荐 - 历史上的今天 API

引言 历史上的今天&#xff0c;总会有一些特别的事件发生&#xff0c;这些事件对人类的发展产生了深远的影响。想要了解这些事件&#xff0c;往往需要花费大量的时间和精力去查阅历史资料。但现在&#xff0c;有了历史上的今天 API&#xff0c;一切变得方便了许多。 如果你对…

3年外包终上岸,我只能说这类公司能不去就不去····

我大学学的是计算机专业&#xff0c;毕业的时候&#xff0c;对于找工作比较迷茫&#xff0c;也不知道当时怎么想的&#xff0c;一头就扎进了一家外包公司&#xff0c;一干就是3年。现在终于跳槽到了互联网公司了&#xff0c;我想说的是&#xff0c;但凡有点机会&#xff0c;千万…

SAP KANBAN 从入门到放弃系列之调拨模式

之前已经有三篇文章写了后台配置相关的介绍&#xff0c;这里不赘述。详见&#xff1a; PP-KANBAN-看板概述 SAP KANBAN 从入门到放弃系列之生产补货模式 SAP KANBAN 从入门到放弃系列之采购补货模式 第一步&#xff1a;补货策略-转库。不同的补充策略的控制类型有不同的作用…

6.3 收敛性与稳定性

6.3.1 收敛性 数值计算方法的收敛性是指&#xff0c;当取步长趋近于零时&#xff0c;数值解趋近于精确解的速度。一般来说&#xff0c;数值计算方法的收敛性是判断其优劣的重要指标之一。 数值计算方法的收敛性可以通过数学分析来研究&#xff0c;一般需要对数值解和精确解之…

淘宝天猫数据分析:2023年健康养生三大品类数据分析

随着人们健康意识的不断增强&#xff0c;越来越多的年轻人都开始加入养生大军的队伍中&#xff0c;我国的健康养生产业也迎来了发展机遇。 在天猫平台上&#xff0c;养生茶、养生壶和滋补养生原料是养生市场的几大重点类目&#xff0c;接下来&#xff0c;结合鲸参谋电商数据分析…

【论文笔记】VideoGPT: Video Generation using VQ-VAE and Transformers

论文标题&#xff1a;VideoGPT: Video Generation using VQ-VAE and Transformers 论文代码&#xff1a;https://wilson1yan. github.io/videogpt/index.html. 论文链接&#xff1a;https://arxiv.org/abs/2104.10157 发表时间&#xff1a; 2021年9月 Abstract 作者提出了…

Java 之 String、StringBuffer与StringBuilder 区别

String String 是被 final 修饰的类&#xff0c;不能被继承&#xff1b;String实现了 Serializable 和Comparable接口&#xff0c;表示String支持序列化和可以比较大小&#xff1b;String底层是通过char类型的数据实现的&#xff0c;并且被final修饰&#xff0c;所以字符串的值…

Discourse Google Analytics 3 的升级提示

根据 Google 官方的消息&#xff1a; Google Analytics&#xff08;分析&#xff09;4 是我们的新一代效果衡量解决方案&#xff0c;即将取代 Universal Analytics。自 2023 年 7 月 1 日起&#xff0c;标准 Universal Analytics 媒体资源将停止处理新的命中数据。如果您仍在使…

camunda流程引擎receive task节点用途

Camunda的Receive Task用于在流程中等待外部系统或服务发送消息。当接收到消息后&#xff0c;Receive Task将流程继续执行。Receive Task通常用于与Send Task配合使用&#xff0c;以便流程可以在发送和接收消息之间进行交互。 Receive Task可以用于以下场景&#xff1a; 1、等…

abaqus和ansys做仿真哪个更好

当你要模拟仿真一个机械模型时&#xff0c;通常会听到ABAQUS或ANSYS&#xff0c;最常见的问题是哪个更好&#xff1f;无论是工程设计师还是初学者&#xff0c;通常会问这个问题或类似的问题。在本文中介绍了 Abaqus 与 Ansys&#xff0c;您将了解这些问题的答案。 1-ANSYS&…

C++类与对象—上

本期我们来学习类与对象 目录 面向过程和面向对象初步认识 类的引入 访问限定符 类的定义 封装 类的作用域 类的实例化 this指针 C语言和C实现Stack的对比 面向过程和面向对象初步认识 C 语言是 面向过程 的&#xff0c; 关注 的是 过程 &#xff0c;分析出求解问题的…

ajax写法和json的知识点

1. JQuery方式来实现AJAX 1.1 $.ajax()方式来实现AJAX 语法&#xff1a;$.ajax(url,[settings]);但是我们一般这么写$.ajax({键值对});。 $.ajax()来实现ajax的案例&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"…

第二十六章 案例TodoList 之实现Footer组件

本小节&#xff0c;我们来实现最后的Footer组件的功能&#xff0c;它的功能主要有&#xff1a; 记录已完成和全部的任务列表数量点击【复选框】可以实现全选和全不选点击【删除已完成】按钮&#xff0c;可以将选中的任务项删除掉 实现已完成和全部的任务列表数量 步骤1&#…

OJ刷题 第十二篇

21308 - 特殊的三角形 时间限制 : 1 秒 内存限制 : 128 MB 有这样一种特殊的N阶的三角形&#xff0c;当N等于3和4时&#xff0c;矩阵如下&#xff1a; 请输出当为N时的三角形。 输入 输入有多组数据&#xff0c;每行输入一个正整数N&#xff0c;1<N<100 输出 按照给出…

【技巧】如何修改PDF文件?

PDF文件格式安全、标准化&#xff0c;很多人在工作中几乎离不开。可有些小伙伴想要修改PDF文件内容时&#xff0c;发现无法修改&#xff0c;那是什么情况呢&#xff1f;如何才能修改PDF文件呢&#xff1f;下面小编就来分享一些小技巧。 技巧一&#xff1a;使用PDF编辑器 如果使…

美国肝素钠专用树脂,医药肝素钠提取工艺专用树脂

具有控制孔径的大孔强碱性Ⅰ型阴离子交换树脂 Tulsimer A-72 MP 是一款具有便于颜色和有机物去除的控制孔径的&#xff0c;专门开发的大孔强碱性Ⅰ型阴离子交换树脂。 Tulsimer A-72 MP专门应用于去除COD以及其他有机物等。 Tulsimer A-72 MP 由于其本身的大孔特性而显示出…

差分运算放大电路原理解析

差分运算放大电路&#xff0c;对共模信号得到有效抑制&#xff0c;而只对差分信号进行放大&#xff0c;因而得到广泛的用。 注&#xff1a; &#xff08;1&#xff09;共模信号   共模信号&#xff08;common mode signal&#xff09;是指同时作用于多个电路或电子设备上的信…

Spring

目录 &#x1f43c;今日良言:道阻且长,行则将至 &#x1f407;一、Spring介绍 &#x1f407;二、Spring创建和使用 &#x1f407;三、Spring读取和存储对象 &#x1f407;四、Bean作用域和生命周期 &#x1f43c;今日良言:道阻且长,行则将至 &#x1f407;一、Spring介绍…