每日一 R「08」类型系统(二)
今天我们将继续学习多态的另外两种方式:特设多态和子类型多态。首先来简单回顾一下:特设多态指同一种行为有很多不同的实现,例如面向对象语言中的方法重载;子类型多态是指子类型可以当作父类型使用,例如面向对象语言中的里氏替换原则。
Rust 中特设多态和子类型多态的实现都与 trait 相关,trait 可以类比于 Java 中的接口。例如:
Trait 中的方法可以有缺省实现。为某个数据结构实现特定 trait 时,可以重新定义、覆盖缺省实现,但必须实现仅声明却未实现的关联方法(关于关联方法的介绍,参考“03-扩展”)。
01-特设多态
Trait 将数据结构中的行为抽取出来,使其可以在多个类型之间共享,也可作为类型约束,限制传入参数必须具备某些行为(实现特定的 trait)。
如前面介绍的那样,基本 trait 比较容易理解,可以类比其他语言中的概念来理解。Trait 也支持一些高级用法,例如关联类型。
在 trait 中可以声明关联类型,也可以通过类型限定语法: xxx
限定关联类型。例如:
Trait 中的 “type E” 是声明,”: Debug” 是对 E 的类型限定,即 E 必须实现了 Debug trait。impl 中 “type E = T” 指定了 E 的具体类型。关联类型允许用户把 trait 中使用的类型延迟到实现 trait 时,而非声明时。因此,带有关联类型的 trait 比基本 trait 更灵活,抽象度也更高。
Trait 也可以支持泛型。Trait 为什么需要支持泛型?考虑如下场景,如果我们有一个自定义结构 Complex(复数),我们想为它实现 Add trait,让其支持与 Complex 相加,应该怎么定义?可以按照如下实现:
但如果我们想实现 Complex 与 u32 相加呢?怎么实现呢?虽然用上面的方式也能够实现类似的功能,但需要写的代码就非常多,也不够优雅。
带泛型参数的 trait 在这个情形下就非常有用了。上面的代码可以修改为:
Rust 中,trait 可以“继承”另外一个 trait 中声明的关联函数和关联类型,即在自己的声明中使用“继承”来的关联项。例如,trait B: A 表示任何类型 T,如果实现了 trait B,也必须实现 trait A。考虑如下示例:
意思是为所有实现了 Stream trait 的类型 T 实现 StreamExt trait。所以,如果某个类型实现了 Stream trait,它也一定实现了 StreamExt trait。
通过定义 trait 以及为不同的类型实现这个 trait,我们就已经实现了特设多态。
02-子类型多态
虽然 Rust 中不支持继承,但是 trait 与实现 trait 的类型之间是类似的关系。在对函数入参进行类型限定时,可以使用”impl xxx” 来限定参数的具体必须实现 xxx trait。以下两种写法是等价的:
但是这种本质上是泛型,所以会在编译时进行单态化处理。但有时编译时并不知道运行时的具体类型,所以需要一种方式可以告诉编译器,这是实现了某个 trait 的类型,但并不知道具体的类型。Rust 中使用 trait object 实现,语法是 &dyn Trait 或者 Box<dyn Trait>。这种方式是动态分派。
03-扩展
关联项(Associated Items)指与某个类型关联的项。主要包括三类:关联函数、关联类型和关联常量。
Associated Items are the items declared in traits or defined in implementations. They are called this because they are defined on an associate type — the type in the implementation.
关联函数是指于某个类型关联的函数。根据关联项的定义,关联函数指 trait 中声明或 impl 中定义的函数,其关联的类型即实现 trait 的数据结构或 impl … for 指定的数据结构。例如:
new 是 Struct 的关联函数,调用方式为 Struct::new(),from_i32 是 f64 的关联函数,调用方式为 f64::from_i32()。
如果关联函数的第一个参数是 Self / self / &self / &mut self,也称关函数为方法(method)。方法可以通过 xxx.function_name() 形式的语法调用。
[1] Associated Items
本节课程链接:《13|类型系统:如何使用trait来定义接口?》
历史文章推荐
版权声明: 本文为 InfoQ 作者【Samson】的原创文章。
原文链接:【http://xie.infoq.cn/article/862bfde9b89704bac0f47362d】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论