【Rust自学】10.2. 泛型

发布时间:2026/7/23 18:50:54

【Rust自学】10.2. 泛型
10.2 泛型10.2.1. 什么是泛型泛型的主要作用是提高代码的复用性。它们适合处理重复代码问题也可以看成是把数据与算法分离。泛型是具体类型或其他属性的抽象替代。换句话说你写的泛型代码并不是最终代码而更像是一种带有一些占位符的模板。编译器会在编译时把这些占位符替换成具体类型。看个例子fn largestT(list:[T]) - T { //...... }这个函数定义使用了泛型类型参数。T就是所谓的“占位符”。写代码时T可以表示任意类型但在编译时编译器会根据实际用法把T替换成具体类型。这个过程叫做单态化。T是泛型类型参数。实际上你可以使用任意合法标识符作为类型参数名但按惯例通常使用大写字母T代表 Type。选择泛型类型参数名时通常会非常短一个字母往往就够了。如果确实想写长一点使用驼峰命名即可。10.2.2. 函数定义中的泛型用泛型定义函数时需要把泛型类型参数放在函数签名里。泛型类型参数通常用于指定参数类型和返回类型。以 10.1 提取函数以消除重复代码 的代码为例这里做一点泛型修改fn largestT(list: [T]) - T{ let mut largest list[0]; for item in list{ if item largest{ largest item; } } largest }可以把整个函数定义理解成函数largest有一个泛型类型参数T它接收一个切片作为参数切片中的元素类型是T返回值类型也是T。尝试编译一下输出是error[E0369]: binary operation cannot be applied to type T -- src/main.rs:4:17 | 4 | if item largest{ | ---- ^ ------- T | | | T | help: consider restricting type parameter T with trait PartialOrd | 1 | fn largestT: std::cmp::PartialOrd(list: [T]) - T{ | 这里先不讨论原因和修复方法。你只需要知道泛型参数大概就是这样写的。后面的文章会讲解如何指定某个特定的 trait。10.2.3. struct 定义中的泛型结构体中定义的泛型类型参数主要用在其字段上。例如struct PointT { x: T, y: T, } fn main() { let integer Point { x: 5, y: 10 }; let float Point { x: 1.0, y: 4.0 }; }在结构体名称后面加上并在其中写入泛型参数名这个泛型类型就可以应用到结构体的各个字段上。在main中实例化了这个结构体。integer中的两个字段都是i32float中的两个字段都是f64。因为x和y都被声明为T所以实例化后的x和y也必须是同一类型。这两个类型必须保持一致。如果我想让x和y是两种不同的类型呢很简单声明两个泛型类型参数。struct PointT, U { x: T, y: U, } fn main() { let integer Point { x: 5, y: 1.0 }; let float Point { x: 1.0, y: 40 }; }此时实例化后的x和y可以是不同类型当然也可以是相同类型。需要注意的是虽然允许多个泛型类型参数但太多泛型会降低可读性。通常这意味着代码应该被重组为更多、更小的单元。10.2.4. enum 定义中的泛型与结构体很像枚举中的泛型类型参数主要用在其变体中让枚举变体可以持有泛型数据类型。最常见的例子是OptionT和ResultT, E。例如enum OptionT { Some(T), None, } enum ResultT, E { Ok(T), Err(E), }在Option枚举中Some(T)是持有类型为T的值的变体而None变体表示不持有任何值。正因为Option枚举使用了泛型无论这个可能存在的值是什么类型都可以用OptionT来表示同样枚举也可以使用多个泛型类型参数。例如Result枚举使用了T和EOk变体存储TErr变体存储E10.2.5. 方法定义中的泛型方法可以附加在枚举或结构体上。既然枚举和结构体可以使用泛型参数方法当然也可以如下所示struct PointT { x: T, y: T, } implT PointT { fn x(self) - T { self.x } }x方法本质上是一个 getter。为PointT实现方法时需要在impl关键字后面加上T。这表示该实现是针对泛型T的而不是针对某个具体类型。当然如果是为某个具体类型实现方法就不需要那样写impl Pointi32 { fn x1(self) - i32 { self.x } }x1方法只存在于具体类型Pointi32上其他PointT类型没有这个方法类似于 C 中的特化和偏特化。还有一点很重要结构体中的泛型类型参数可以与方法中的泛型类型参数不同。例如struct PointT, U { x: T, y: U, } implT, U PointT, U { fn mixupV, W(self, other: PointV, W) - PointT, W { Point { x: self.x, y: other.y, } } } fn main() { let p1 Point { x: 5, y: 10.4 }; let p2 Point { x: Hello, y: c }; let p3 p1.mixup(p2); println!(p3.x {}, p3.y {}, p3.x, p3.y); }为PointT, U实现了方法mixup。它有两个泛型类型参数V和W。方法中的这两个类型参数与Point中的两个类型参数不同尽管实际类型最终也可能相同。mixup的第二个参数是other它的类型也是Point但这个Point不一定与self所指向的Point使用相同的数据类型因此需要两个新的泛型类型参数。再看返回类型它是PointT, WT来自PointT, UW来自PointV, W。现在看main先声明p1它的两个字段分别是i32和f64再声明p2它的两个字段分别是str字符串切片和char用表示的单个字符。接着使用mixup。p1对应PointT, Up2对应PointV, W。根据它们的字段类型可以推断T是i32U是f64V是strW是char。mixup的返回类型是PointT, W在这个例子中就是Pointi32, char。输出p3.x 5, p3.y c10.2.6. 泛型代码的性能使用泛型编写的代码运行速度与使用具体类型编写的代码一样快。Rust 会在编译时执行单态化把泛型类型替换成具体类型因此执行时不存在类型替换过程。例如fn main() { let integer Some(5); let float Some(5.0); }这里integer是Optioni32float是Optionf64。在编译时编译器会把OptionT展开为Option_i32和Option_f64enum Option_i32 { Some(i32), None, } enum Option_f64 { Some(f64), None, }也就是说泛型定义OptionT被替换成了两个具体类型定义。单态化后的main函数也会变成这样enum Option_i32 { Some(i32), None, } enum Option_f64 { Some(f64), None, } fn main(){ let integer Option_i32::Some(5); let float Option_f64::Some(5.0); }

相关新闻

【Rust自学】10.3. trait Pt.1:trait的定义、约束与实现

【Rust自学】10.3. trait Pt.1:trait的定义、约束与实现

2026/7/23 18:50:54

10.3 trait Pt.1:trait的定义、约束与实现 10.3.1. 什么是trait trait 的意思是特征、特质。trait 用来向 Rust 编译器描述某个类型具有哪些能力,以及它可以与其他类型共享哪些行为。trait 以抽象方式定义共享行为。 还有 trait bounds(约束&…

【JavaScript】Javascript—APIs—Day01

【JavaScript】Javascript—APIs—Day01

2026/7/23 18:40:54

Javascript——Day0601. 声明变量const优先02. DOM树和DOM对象03. 获取DOM元素04. DOM修改元素内容以及年会抽奖案例05. DOM修改元素常见属性以及案例06. 通过style修改样式07. 通过类名修改样式08. 通过classList修改样式09. 随机轮播图案例10. 获取设置表单的值11. H5自定义属…

Unity强化学习实战项目—自动泊车「Unity+MLagent」—效果展示【源码在文末】

Unity强化学习实战项目—自动泊车「Unity+MLagent」—效果展示【源码在文末】

2026/7/23 18:40:54

Unity强化学习实战项目—自动泊车「UnityMLagent」—效果展示【源码在文末】 文章目录Unity强化学习实战项目—自动泊车「UnityMLagent」—效果展示【源码在文末】一、内容与步骤二、效果展示三、源码一、内容与步骤 1、搭建一个简单的停车场模型并实现小车运动,要…

Python计算机毕设之基于 Python 的期货行情展示与模拟交易系统 零基础期货实训虚拟交易平台设计(完整前后端代码+说明文档+LW,调试定制等)

Python计算机毕设之基于 Python 的期货行情展示与模拟交易系统 零基础期货实训虚拟交易平台设计(完整前后端代码+说明文档+LW,调试定制等)

2026/7/23 19:40:56

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

Python计算机毕设之基于 Python 的校园二手社交交易平台实现校园二手物品问答互动与交易系统设计 (完整前后端代码+说明文档+LW,调试定制等)

Python计算机毕设之基于 Python 的校园二手社交交易平台实现校园二手物品问答互动与交易系统设计 (完整前后端代码+说明文档+LW,调试定制等)

2026/7/23 19:40:56

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

具身智能进入“干活时代“:从展台演示到真实部署,数据才是核心瓶颈

具身智能进入“干活时代“:从展台演示到真实部署,数据才是核心瓶颈

2026/7/23 19:40:56

具身智能进入"干活时代":从展台演示到真实部署,数据才是核心瓶颈2026年7月中旬,国内规模最大的人工智能展会在上海举办。展览总面积首次突破10万平方米,超过1100家企业参展,3000余件展品中有300多件为全球首…

GEE中的几个小技巧

GEE中的几个小技巧

2026/7/23 19:40:56

1.如何上传你要的区域:准备你所在区域的shp(有四个文件)主页点击1.Assets 2.Shape files 3.Select 把四个文件都传上去 4.命名你的区域Assets下有文件就是传成功了 然后切到Scripts就可以调用了// 定义研究区域 var region ee.FeatureCollection(projects/ee-jiuwa…

嵌入式系统参数动态更新利器:TI MCU POM模块原理与实战

嵌入式系统参数动态更新利器:TI MCU POM模块原理与实战

2026/7/23 19:40:56

1. 项目概述:为什么我们需要POM?在嵌入式系统开发,尤其是汽车电子、工业控制这类对实时性和可靠性要求极高的领域,我们经常面临一个经典难题:如何在产品部署后,甚至在系统运行时,动态地调整程序…

J4105 工控小主机刷写 Proxmox VE 及部署 OpenWrt 与 Home Assistant OS完整指南

J4105 工控小主机刷写 Proxmox VE 及部署 OpenWrt 与 Home Assistant OS完整指南

2026/7/23 19:30:56

J4105 工控小主机刷写 Proxmox VE 及部署 OpenWrt 与 Home Assistant OS完整指南 本文档详细介绍 J4105 工控小主机的刷机流程,核心分为准备工作、安装 Proxmox VE(PVE)、创建 OpenWrt 与 Home Assistant OS 虚拟机三大步骤,每一步均包含具体工具、操作细节及注意事项,确…

微服务进阶:服务网格与Istio

微服务进阶:服务网格与Istio

2026/7/23 3:40:08

541|微服务进阶:服务网格与Istio 上篇文章我们聊了微服务的基本概念和拆分方法。 但微服务多了,问题也多了: 服务之间怎么通信? 怎么监控每个服务的调用链路? 熔断、限流、重试怎么做? 安全认证怎么统一? 以前这些都靠SDK库(比如Hystrix、Feign),每个服务都要集成…

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

2026/7/23 4:40:05

一、零售门店全域协同业务背景与行业痛点 1.1 门店超级终端设备矩阵(连锁便利店/商超标准配置) 自助收银Kiosk一体机:顾客结算、自助核销优惠券、商品素材预览;运营折叠平板:店长后台商品上新、图片录入、活动配置、…

噗叽短视频界面分析

噗叽短视频界面分析

2026/7/23 1:54:13

1 和小红书类似,可以采用类似判断方法------------其实他比小红书好判断,因为他没有图片,控件位置几乎是固定的,都不用判断------------2 因为他没有点赞按钮------------而且几乎所有控件位置都是完全一样的,所以我就…

企业级AI搜索落地选型实战手册(含LLM+RAG+Hybrid架构对比矩阵与ROI测算模板)

企业级AI搜索落地选型实战手册(含LLM+RAG+Hybrid架构对比矩阵与ROI测算模板)

2026/7/23 0:09:56

更多请点击: https://kaifayun.com 第一章:企业级AI搜索落地选型实战手册(含LLMRAGHybrid架构对比矩阵与ROI测算模板) 企业级AI搜索系统落地成败,核心在于技术选型与业务价值的精准对齐。盲目堆砌大模型能力或过度依赖…

TM4C129LNCZAD外设实战:LCD、比较器与PWM寄存器配置详解

TM4C129LNCZAD外设实战:LCD、比较器与PWM寄存器配置详解

2026/7/23 0:09:56

1. 项目概述与核心价值在嵌入式系统开发,尤其是基于ARM Cortex-M内核的微控制器项目中,深入理解并熟练配置芯片的片上外设,是从“点亮LED”迈向“实现复杂系统功能”的关键一步。Tiva™ TM4C129LNCZAD作为TI公司Cortex-M4F家族中的高性能成员…

AtomCode `fmt_dur` 争议溯源:两个函数、三段演进、四个事实

AtomCode `fmt_dur` 争议溯源:两个函数、三段演进、四个事实

2026/7/23 0:09:56

一、快速声明与争议背景本文是对 AtomCode 终端 spinner 时长显示 fmt_dur 相关说法的事实性核验。2026 年 7 月 CSDN 上出现两篇互相矛盾的博文,近期又有 AI 在对话中输出格式描述 XhYm / YmZs / Zs。本文基于 AtomCode 仓库 main4677ddfa 及全分支 Git 历史给出可…