泛型
泛型是一种参数化多态,使用泛型可以编写更为抽象的代码,减少工作量,简单来说,泛型就是把一个泛化的类型作为参数,单个类型可以抽象化为一簇类型。
rust在编译时期会把泛型枚举,函数,结构体单态化。
单态化意味着编译器要将一个泛型函数生成多个具体类型对应的函数。
单态化是编译器进行静态分发的一种策略。
单态化静态分发的好处是性能好,没有运行时开销,缺点是容易造成编译后生成的二进制文件膨胀。
trait是在行为上对类型的约束。
使用场景
接口抽象,接口是对类型行为的统一约束
泛型约束,泛型的行为被trait限定在更有限的范围内
抽象类型,在运行时作为一种间接的抽象类型去使用,动态的分发给具体的类型
标签trait,对类型的约束,可以直接作为一种“标签”使用。
接口抽象
trait最基本的用法就是进行接口抽象,它有如下特点:
- 接口中可以第一方法,并支持默认实现
- 接口中不能实现另一个接口,但是接口之间可以继承
- 同一个接口可以同时被多个类型实现,但不能被同一个类型实现多次
- 使用impl关键字为类型实现接口方法
- 使用trait关键字来定义接口
trait关联类型
使用关联类型能够是代码变得更加精简,同时也对方法的输入和输出进行来更好的隔离,使得代码的可读性大大增强。在语义层面上,使用关联类型也增强来trait表示行为的这种语义,因为它表示来和某个行为(trait)相关联的类型,在工程上也提现了高内聚的特点。
孤儿规则
孤儿规则规定,如果实现某个trait,那么该trait和要实现该trait的那个类型至少有一个要在当前create中定义。
trait继承
子trait可以继承父trait中定义或实现的方法。
trait后面的冒号代表trait继承,其后跟随要继承的父trait名称,如果是多个trait则用加号相连;
泛型约束
trait限定
使用trait对泛型进行约束叫trait限定。
在泛型中使用trait限定可以将任意类型的范围根据类型的行为限定到更加精确可控的范围内。
trait可以使用where关键字对较多的限定的代码进行重构。
在作为泛型限定时,Rust中冒号代表集合的“包含于”关系,而加号代表这种限定行为交集。
trait限定给予了开发者更大的自由度,因为不再需要类型间的继承,也简化了编译器的检查操作,包含trait限定的泛型属于静态分发,在编译期通过单态化分别生成具体类型的实例,所以调用trait限定中的方法也都是运行是零成本的,因为不需要在运行时进行方法查找。
抽象类型
抽象类型属于类型系统的一种,也叫存在类型,相对于具体类型而言,抽象类型无法直接实例化,它的每个实例都是具体类型的实例。
对于抽象类型而言,编译器可能无法确定其确切的功能和所占的空间大小,所以rust目前有两种方法来处理抽象类型,trait对象和impl trait
trait对象
trait对象是对具有相同行为的一组具体类型的抽象,将共同拥有相同行为的类型集合抽象为一个类型。
traitObject包含两个指针:data指针和vtable指针
impl trait
impl Trait只可以在输入的参数和返回值这两个位置使用。
impl trait用在参数位置时等价于使用trait限定的泛型。impl trait用在返回值位置的时候等价于给返回值类型增加一种trait限定范围。
标签trait
rust一共提供了5个重要的标签trait,都被定义在标准库std::marker模块中
- Sized trait,用来标示编译期可确定大小的类型
- Unsize trait,目前该trait为实验特性,用于标示动态大小类型
- Copy trait,用来标示可以安全地按位复制其值的类型。
- Send trait,用来标示可以跨线程安全通信的类型
- Sync trait,用来标示可以在线程间安全共享引用的类型。
Copy trait
copy 是一个标签trait,编译器做类型检查时会检测类型所带来的标签,以验证它是否“合格”,copy的行为是一个隐式行为,开发者不能重载copy行为,它永远都是一个简单的位复制。
并非所有类型都可以实现copy trait ,对于自定义类型来说,必须让所有的成员都实现了copy trait这个类型才有资格实现copy trait。
clone trait是一个显式行为,任何类型都可以实现clone trait
Send trait 和Sync trait
rust提供了语言级的并发支持,rust凭借Send、Sync和所有权机制,在编译时期就检查出线程安全问题,保证了无数据竞争的的并发安全问题,让开发者可以“无恐慌”地编写多线程并发代码。
rust提供了Send和Sync两个标签trait,它们是rust无数据竞争开发的基石。
实现send的类型,可以安全地在线程间传递值,也就是说可以跨线程传递所有权。
实现了sync的类型,可以跨线程安全地传递共享(不可变)引用。
send 和sync标签trait和前面所说的copy,sized一样,内部也没有具体的方法实现,它们仅仅是标记可以安全的跨线程传递和访问的类型用send和sync标记,否则使用!send 和!sync标记
网友评论