《Rust 编程第一课》 学习笔记 Day 21

284 阅读3分钟

大家好,我是砸锅。一个摸鱼八年的后端开发。熟悉 Go、Lua。第二十一天还是继续和大家一起学习 Rust😊

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情

Rust 类型系统

类型系统其实就是对类型进行定义、检查和处理的系统

多态是指在使用相同的接口时,不同类型的对象会采用不同的实现,对于静态类型系统,多态可以通过参数多态、特设多态、子类型多态来实现:

  1. 参数多态指的是,代码操作的类型是一个满足某些约束的参数,而非具体的类型
  2. 特设多态是指,同一种行为有多个不同实现的多态,一般指函数的重载
  3. 子类型多态是指,在运行时子类型可以被当成父类型使用

在 Rust 里,参数多态是通过泛型来实现,特设多态是通过 trait 来实现,子类型多态可以用 trait object 来实现

image.png 在定义时,Rust 不允许类型隐式转换,所以说 Rust 是强类型语言。同时在检查时,Rust 使用了静态类型系统,在编译期间保证类型正确,强类型加上静态类型,这也是 Rust 被称为类型安全的原因,代码只能按照被允许的方法和被允许的权限,访问它被授权访问的内存

在 Rust 里,对于一个作用域,最后一个表达式返回值就是作用域的返回值,如果表达式或者函数不返回任何值,则返回一个 unit(),unit 是只有一个值的类型,它的值和类型都是 ()。这个 unit() 有点像 Go 里面的 _ ,不关心值的时候可以用这个。例如 Result<(), Error>,表示只关心错误的返回内容,不关心成功的返回内容

数据类型

image.png Rust 的原生类型包括字符、整数、浮点数、布尔值、数组、元组、切片、指针、引用、函数等

image.png

Rust 标准库支持的组合类型:

image.png

泛型数据结构

enum Option<T> {
	Some(T)
	None,
}

函数就是将重复代码中的参数抽取出来,使其更加通用,调用函数时,根据参数不同,得到不同的结果

泛型就是把重复数据结构中参数抽取出来,使用泛型类型时,根据不同参数,得到不同的类型

Cow(Clone-on-Write) 是 Rust 里面的数据结构,和 Option 一样,返回数据的时候,要么返回一个借用的数据(只读),要么返回一个拥有所有权的数据(可写)

在表述泛型参数的约束时,Rust 允许两种方式:

  1. 类似函数参数的类型声明,用” : ” 来表示约束,多个约束之间用 + 来表示
  2. 另一种用 where 子句,在定义的结尾来表明参数的约束

泛型函数

在声明一个函数的时候,可以不指定具体的参数或者返回值的类型,而是用泛型参数来代替:

fn in<T>(x: T) -> T {
	return x;
}

fn main() {
	let int = id(10);
	let string = id("Try");
	println!("{}, {}", int, string);
}

对于泛型函数,Rust 会进行单态化处理,也就是在编译时把所有用到的泛型函数的泛型参数展开,生成若干个函数

单态化好处是:泛型函数的调用是静态分派(static dispatch),在编译时就一一对应,保证多态的灵活性也没有任何效率的损失

缺点是:但是会导致编译速度变慢,因为一个泛型函数编译器就要找到所有用到的不同类型,一个个编译。这也导致了生成的二进制文件很大,因为泛型函数的二进制代码存在多份