坏蛋Dan
知乎@坏蛋Dan
发布时间:2024.1.4

前言

昨天我们说了下rust推荐的使用panic的场景

坏蛋Dan:rust基础学习--day20

今天该学第十章了。


泛型

前面已经多次提到过泛型了,另外在别的语言中你应该也有接触过,比如typescript

rust中,泛型可以用于functionstruct以及enum等中。我们先来学下如何创建相应的泛型。

定义一个带有泛型的函数

我们直接来看下例子

规范是放在函数名字之后()之前 ,用<>包裹中间的泛型,一般都是用缩写的大写字母。如果需要多个泛型,可以用,隔开。比如``。

好像没什么用?在这个方法中确实没什么用,不过我们可以来看下一个例子

稍微有那么一点长。

我们声明了两个functionlargest_i32largest_char,它们的作用都是用来寻找list中最大的那个元素,然后返回。

这俩函数唯一不同的地方就在于类型,元素的类型不同,但是由于强类型的问题,需要写两套代码,这就很难受。

这个时候我们就可以用泛型,我们来改下代码

这样是不是就少了很多重复代码

不过这里有个报错

不能用泛型来比较大小,这是必然的,因为连类型都不确定。

不过它有个help

这是一个trait,如果这个T标记了这个std::cmp::PartialOrd,那么就可以比较(当然不是所有类型都可以,而这里chari32都实现了这个trait)。下一章就会说到trait,所以这里我们还是跳过。

从这上面的例子可以发现,泛型可以让我们节省下很多重复的逻辑代码。


定义一个带有泛型的构造体

直接开看下例子

规范是定义在名字和{}之间

但是构造体有一个特点,就是类型可以不同,所以往往一个T并不能满足所有需求,比如

这样就有问题了,xi32,而yf64

所以这个时候得改下我们的泛型定义

这样就没问题了


在枚举中使用泛型

最典型的就是我们的OptionResult了。

就不多说了


在method中使用泛型

来看下例子

开始有那么一点复杂了。。

这里有两个T,一个是impl后面的,一个是Point后面的,而 -> &T这个是impl后面的T,而Ponit后面的T实际上也是impl后面那个T,我们来改下impl后面那个T

结果发现俩T都不得劲了。

那到底啥意思呢?

我们再来看个例子

只有Point的类型可以使用这个distance_from_originmethod

这就很舒服了,不同类型可以有不同的method,并且也不存在错用乱用的情况。当然,如果不确定类型就说明共用,所有类型都能用。

我们再来看个例子

这个例子就有点复杂了。。。这个mixup方法实际上是将自己的x和另一个实例的y结合,生成一个新的实例,类型是Point

有四个泛型X1,Y1,X2,Y2,其中Point后面的只能用这个X1,Y1,因为X2,Y2都是mixup这个方法的泛型。

也就是说这个同样是受限于作用域规则。


使用泛型的性能

你应该会担心这玩意儿的性能问题(其实并没有),由于类型并不固定,所以会担心有runtime的花费(不好意思,也没有)。

实际上并没有runtime的花费,因为rust在编译的时候使用泛型来执行代码的单态化(monomorphization)使得runtime之前就确定下来了。这句话我翻译的应该不是很对。。。我把原文贴出来

啥意思呢?看着好高端的样子,实际上只是用一种特殊的方式执行这段代码然后确定下来类型而已,简单地说就是在编译的时候做类似runtime的操作确定下来类型(monomorphization是一个process也就是进程)。

我们来看个例子

这是一个Option的变体,它的值是一个泛型,在编译的时候发现了这段代码,monimorphization就开始运行啦,然后它跑完全部代码之后发现使用Option的枚举泛型有两个,一个是Option,一个是Option,这个时候它就会把Option拓展为i32f64的类型。这样你这代码的类型就固定下来了,也就是不再存在T,而是i32f64

简单的说就像是语法糖,编译的时候会帮你编译成你手动去固定类型一样。如下面这段代码

看起来好像很6

其实各位如果看过一些框架的编译器源码(比如说vuesfc编译器),你就不会觉得这操作666了。


总结

今天我们学了泛型,使用上和其他语言的泛型有点差别,但是不大。

最后如果觉得这篇文章对你有帮助的话,请务必点个赞,谢谢·~

参考

  1. ^rust-generic-data-types https://doc.rust-lang.org/book/ch10-01-syntax.html
  2. ^rust-function-defining-with-generic https://doc.rust-lang.org/book/ch10-01-syntax.html#in-function-definitions
  3. ^rust-struct-defining-with-generic https://doc.rust-lang.org/book/ch10-01-syntax.html#in-struct-definitions
  4. ^rust-enum-defining-with-generic https://doc.rust-lang.org/book/ch10-01-syntax.html#in-enum-definitions
  5. ^rust-use-generic-in-method-defining
  6. ^rust-performance-of-code-using-generic https://doc.rust-lang.org/book/ch10-01-syntax.html#performance-of-code-using-generics

发布于 2022-12-14 22:47・IP 属地广东