类型系统
1. 概述
- 类型大小, 类型在内存中对⻬、布局
- 类型推导
- 泛型
Trait- 类型转换
- 多态
Rust是一⻔显式静态强类型的类型安全语言
- 显式: 是因为它的类型推导在某些时候需要显示指定
- 静态: 表明它在编译期进行类型检查
- 强类型: 表明它不允许类型自动隐式转换,不同类型无法进行计算
- 类型安全: 表明它保证运行时的内存安全, 只能按照被允许的方法, 访问它被授权访问的内存

2 类型大小
2.1 可确定大小类型
use std::mem;
fn main() {
println!("{}", mem::size_of::<bool>());
println!("{}", mem::size_of::<u8>());
println!("{}", mem::size_of::<i8>());
println!("{}", mem::size_of::<u16>());
println!("{}", mem::size_of::<i16>());
println!("{}", mem::size_of::<u32>());
println!("{}", mem::size_of::<i32>());
println!("{}", mem::size_of::<f32>());
println!("{}", mem::size_of::<f64>());
println!("{}", mem::size_of::<char>());
println!("{}", mem::size_of::<()>());
}
2.2 动态大小类型
fn main() {
let str = "hello world";
let prt = str.as_ptr();
let len = str.len();
println!("{:p}", prt);
println!("{:?}", len);
}
2.3 零值类型
零值类型: 类型的特别是可以提高性能或实现某些trait而不关心其数据
use std::mem;
// 零大小类型, 不分配内存空间.
enum Void {} // 空枚举
struct Foo; // 单元结构体
struct Bar {
foo: Foo,
qux: (), // 单元类型
bax: [u8; 0], // 空数组
}
fn main() {
println!("{}", mem::size_of::<()>());
println!("{}", mem::size_of::<Void>());
println!("{}", mem::size_of::<Foo>());
println!("{}", mem::size_of::<Bar>());
println!("{}", mem::size_of::<[(); 10]>());
}
3. 类型推导
3.1 自动推导
// Rust大部份情况下可以根据上下文明推导类型
fn main() {
let a = 1; // 没有标注类型.
let b = 2; // 没有标注类型.
sum(a, b); // Rust 自动推导了a和b的类型.
let elem = 5u8;
let mut vec = Vec::new();
vec.push(elem);
}
fn sum(a: u32, b: i32) -> u32 {
a + (b as u32)
}
3.2 手动标注
// 引入 turbofish 操作符 ::<>
fn main() {
let x = "1";
println!("{:?}", x.parse::<u32>().unwrap());
}
4. 泛型
单态化 零成本抽象的一种实现,
其实在 Rust 里, 生命周期标注也是泛型的一部分, 一个生命周期 'a 代表任意的生命周期, 和 T 代表任意类型是一样的
5. Trait
Rust的trait提供了零成本抽象能力, 它定义了类型使用这个接口的行为
在 trait 中, 方法可以有缺省的实现.
在定义方法的时候, 频繁看到两个特殊的关键字:Self 和 self.
Self代表当前的类型, 比如File类型实现了Write, 那么实现过程中使用到的Self就指代File.self在用作方法的第一个参数时, 实际上是self: Self的简写, 所以&self是self: &Self, 而&mut self是self: &mut Self.
trait 的“继承“
在 Rust 中, 一个 trait 可以“继承”另一个 trait 的关联类型和关联函数. 比如 trait B: A , 是说任何类型 T, 如果实现了 trait B, 它也必须实现 trait A, 换句话说, trait B 在定义时可以使用 trait A 中的关联类型和方法
Trait 如何定义和使用

Trait Object 实现原理

6. 类型转换
无歧义完全限定语法
trait A {
fn test(&self, i: i32) {
println!("from trait A: {:?}", i)
}
}
trait B {
fn test(&self, i: i32) {
println!("from trait B: {:?}", i)
}
}
struct S(i32);
impl A for S {}
impl B for S {}
fn main() {
let s = S(1);
A::test(&s, 2);
<S as A>::test(&s, 2);
B::test(&s, 2);
<S as B>::test(&s, 2);
}

7. 多态
静态类型系统, 多态可以通过参数多态(parametric polymorphism)、特设多态(adhoc polymorphism)和子类型多态(subtype polymorphism)实现.
- 参数多态是指, 代码操作的类型是一个满足某些约束的参数, 而非具体的类型.
Rust通过泛型支持. - 特设多态是指同一种行为有多个不同实现的多态. 比如加法, 可以 1+1, 也可以是 “abc” + “cde”、matrix1 + matrix2、甚至 matrix1 + vector1. 在面向对象编程语言中, 特设多态一般指函数的重载.
Rust通过trait支持. - 子类型多态是指, 在运行时, 子类型可以被当成父类型使用.
Rust通过trait object支持.
在 Rust 中, 参数多态通过泛型来支持、特设多态通过 trait 来支持、子类型多态可以用 trait object 来支持,
7.1 参数多态
它包括泛型数据结构和泛型函数
-
泛型数据结构:
Rust对数据结构的泛型, 或者说参数化类型, 有着完整的支持. 例:Option<T> -
泛型函数: 在声明一个函数的时候, 我们还可以不指定具体的参数或返回值的类型, 而是由泛型参数来代替
7.2 特设多态
包括运算符重载, 是指同一种行为有很多不同的实现
7.3 子类型多态
子类型当成父类型使用, 通过 trait object 来支持,