|
|
@ -3,7 +3,7 @@
|
|
|
|
Go语言在2022年,就要正式引入泛型,被视为在1.0版本后,语言特性发展迈出的一大步,为什么泛型这么重要?到底什么是泛型?Rust的泛型有几种?
|
|
|
|
Go语言在2022年,就要正式引入泛型,被视为在1.0版本后,语言特性发展迈出的一大步,为什么泛型这么重要?到底什么是泛型?Rust的泛型有几种?
|
|
|
|
本章将一一为你讲解。
|
|
|
|
本章将一一为你讲解。
|
|
|
|
|
|
|
|
|
|
|
|
我们在编程中,经常有这样的需求:用同一功能的函数处理不同类型的数据,例如两个数的加法,这两个数可以是整数,也可以是浮点数,甚至是自定义类型,都能进行支持。在不支持泛型的编程语言中,通常需要为每一种类型编写一个函数:
|
|
|
|
我们在编程中,经常有这样的需求:用同一功能的函数处理不同类型的数据,例如两个数的加法,无论是整数还是浮点数,甚至是自定义类型,都能进行支持。在不支持泛型的编程语言中,通常需要为每一种类型编写一个函数:
|
|
|
|
```rust
|
|
|
|
```rust
|
|
|
|
fn add_i8(a:i8, b:i8) -> i8 {
|
|
|
|
fn add_i8(a:i8, b:i8) -> i8 {
|
|
|
|
a + b
|
|
|
|
a + b
|
|
|
@ -26,9 +26,9 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
|
|
在开始讲解Rust的泛型之前,先来看看什么是多态。
|
|
|
|
在开始讲解Rust的泛型之前,先来看看什么是多态。
|
|
|
|
|
|
|
|
|
|
|
|
在编程的时候,我们经常利用多态。通俗的讲,多态就是好比坦克的炮管,这个炮管既可以发射普通弹药,也可以发射制导炮弹(导弹),也可以发射贫铀穿甲弹,甚至发射子母弹,没有必要为每一种炮弹都在坦克上分别安装一个专用炮管,即使生产商愿意,炮手也不愿意,累死人啊。所以在编程开发中,我们也需要这样“通用的炮管”,这个“通用的炮管”就是多态。
|
|
|
|
在编程的时候,我们经常利用多态。通俗的讲,多态就是好比坦克的炮管,既可以发射普通弹药,也可以发射制导炮弹(导弹),也可以发射贫铀穿甲弹,甚至发射子母弹,没有必要为每一种炮弹都在坦克上分别安装一个专用炮管,即使生产商愿意,炮手也不愿意,累死人啊。所以在编程开发中,我们也需要这样“通用的炮管”,这个“通用的炮管”就是多态。
|
|
|
|
|
|
|
|
|
|
|
|
实际上,泛型就是一种多态。泛型主要目的是为程序员提供编程的便利,减少代码的臃肿,同时极大丰富语言本身的表达能力,为程序员提供了一个合适的炮管。想想,一个函数,可以代替几十个,甚至数百个函数,是一件多么让人兴奋的事情:
|
|
|
|
实际上,泛型就是一种多态。泛型主要目的是为程序员提供编程的便利,减少代码的臃肿,同时可以极大地丰富语言本身的表达能力,为程序员提供了一个合适的炮管。想想,一个函数,可以代替几十个,甚至数百个函数,是一件多么让人兴奋的事情:
|
|
|
|
```rust
|
|
|
|
```rust
|
|
|
|
fn add<T>(a:T, b:T) -> T {
|
|
|
|
fn add<T>(a:T, b:T) -> T {
|
|
|
|
a + b
|
|
|
|
a + b
|
|
|
@ -45,7 +45,7 @@ fn main() {
|
|
|
|
## 泛型详解
|
|
|
|
## 泛型详解
|
|
|
|
上面代码的 `T` 就是**泛型参数**,实际上在Rust中,泛型参数的名称你可以任意起,但是出于惯例,我们都用 `T` ( `T` 是 `type` 的首字母)来作为首选,这个名称越短越好,除非需要表达含义,否则一个字母是最完美的。
|
|
|
|
上面代码的 `T` 就是**泛型参数**,实际上在Rust中,泛型参数的名称你可以任意起,但是出于惯例,我们都用 `T` ( `T` 是 `type` 的首字母)来作为首选,这个名称越短越好,除非需要表达含义,否则一个字母是最完美的。
|
|
|
|
|
|
|
|
|
|
|
|
使用泛型参数,有一个先决条件,必需在使用前对泛型参数进行声明:
|
|
|
|
使用泛型参数,有一个先决条件,必需在使用前对其进行声明:
|
|
|
|
```rust
|
|
|
|
```rust
|
|
|
|
fn largest<T>(list: &[T]) -> T {
|
|
|
|
fn largest<T>(list: &[T]) -> T {
|
|
|
|
```
|
|
|
|
```
|
|
|
@ -269,7 +269,7 @@ impl Point<f32> {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## const泛型(Rust 1.51版本引入的重要特性)
|
|
|
|
## const泛型(Rust 1.51版本引入的重要特性)
|
|
|
|
前面讲解的泛型总结起来就是,针对类型实现的泛型,所有的泛型都是为了抽象不同的类型,那有没有针对值的泛型?可能很多同学感觉很难理解,值怎么使用泛型?不急,我们先从数组讲起。
|
|
|
|
在之前的泛型中,可以抽象为一句话:针对类型实现的泛型,所有的泛型都是为了抽象不同的类型,那有没有针对值的泛型?可能很多同学感觉很难理解,值怎么使用泛型?不急,我们先从数组讲起。
|
|
|
|
|
|
|
|
|
|
|
|
在[数组](../compound-type/array.md)那节,有提到过很重要的一点:`[i32; 2]` 和 `[i32; 3]` 是不同的数组类型,比如下面的代码:
|
|
|
|
在[数组](../compound-type/array.md)那节,有提到过很重要的一点:`[i32; 2]` 和 `[i32; 3]` 是不同的数组类型,比如下面的代码:
|
|
|
|
```rust
|
|
|
|
```rust
|
|
|
@ -354,9 +354,10 @@ fn main() {
|
|
|
|
#### const泛型表达式
|
|
|
|
#### const泛型表达式
|
|
|
|
假设我们某段代码需要在内存很小的平台上工作,因此需要限制函数参数占用的内存大小,此时就可以使用const泛型表达式来实现:
|
|
|
|
假设我们某段代码需要在内存很小的平台上工作,因此需要限制函数参数占用的内存大小,此时就可以使用const泛型表达式来实现:
|
|
|
|
```rust
|
|
|
|
```rust
|
|
|
|
|
|
|
|
// 目前只能在nightly版本下使用
|
|
|
|
#![allow(incomplete_features)]
|
|
|
|
#![allow(incomplete_features)]
|
|
|
|
#![feature(generic_const_exprs)]
|
|
|
|
#![feature(generic_const_exprs)]
|
|
|
|
(这段代码编译不通过,Assert处报错,这里泛型的声明好像没有体现出const)
|
|
|
|
|
|
|
|
fn something<T>(val: T)
|
|
|
|
fn something<T>(val: T)
|
|
|
|
where
|
|
|
|
where
|
|
|
|
Assert<{ core::mem::size_of::<T>() < 768 }>: IsTrue,
|
|
|
|
Assert<{ core::mem::size_of::<T>() < 768 }>: IsTrue,
|
|
|
|