继承(Inheritance)是一个很多编程语言都提供的机制,一个对象可以定义为继承另一个对象的定义,
这使其可以获得父对象的数据和行为,而无需重新定义。
如果一个语言必须有继承才能被称为面向对象语言的话,那么 Rust 就不是面向对象的。无法定义一个结
构体继承父结构体的成员和方法。然而,如果你过去常常在你的编程工具箱使用继承,根据你最初考虑
继承的原因,Rust 也提供了其他的解决方案。
选择继承有两个主要的原因。第一个是为了重用代码:一旦为一个类型实现了特定行为,继承可以对一
个不同的类型重用这个实现。相反 Rust 代码可以使用默认 trait 方法实现来进行共享,在示例 10-14 中
我们见过在 Summary trait 上增加的 summarize 方法的默认实现。任何实现了 Summary trait 的类型
都可以使用 summarize 方法而无须进一步实现。这类似于父类有一个方法的实现,而通过继承子类也
拥有这个方法的实现。当实现 Summary trait 时也可以选择覆盖 summarize 的默认实现,这类似于子
类覆盖从父类继承的方法实现。
第二个使用继承的原因与类型系统有关:表现为子类型可以用于父类型被使用的地方。这也被称为 多态
(polymorphism),这意味着如果多种对象共享特定的属性,则可以相互替代使用。
多态(Polymorphism)
很多人将多态描述为继承的同义词。不过它是一个有关可以用于多种类型的代码的更广泛的概念。
对于继承来说,这些类型通常是子类。Rust 则通过泛型来对不同的可能类型进行抽象,并通过 trait
bounds 对这些类型所必须提供的内容施加约束。这有时被称为 bounded parametric polymorphism。
近来继承作为一种语言设计的解决方案在很多语言中失宠了,因为其时常带有共享多于所需的代码的风
险。子类不应总是共享其父类的所有特征,但是继承却始终如此。如此会使程序设计更为不灵活,并引
入无意义的子类方法调用,或由于方法实际并不适用于子类而造成错误的可能性。某些语言还只允许子
类继承一个父类,进一步限制了程序设计的灵活性。
因为这些原因,Rust 选择了一个不同的途径,使用 trait 对象而不是继承。让我们看一下 Rust 中的 trait
对象是如何实现多态的。
为使用不同类型的值而设计的 trait 对象
ch17-02-trait-objects.md
commit 727ef100a569d9aa0b9da3a498a346917fadc979
在第八章中,我们谈到了 vector 只能存储同种类型元素的局限。示例 8-10 中提供了一个定义
SpreadsheetCell 枚举来储存整型,浮点型和文本成员的替代方案。这意味着可以在每个单元中储
存不同类型的数据,并仍能拥有一个代表一排单元的 vector。这在当编译代码时就知道希望可以交替使
用的类型为固定集合的情况下是完全可行的。
然而有时我们希望库用户在特定情况下能够扩展有效的类型集合。为了展示如何实现这一点,这里将创
建一个图形用户接口(Graphical User Interface,GUI)工具的例子,它通过遍历列表并调用每一个项
目的 draw 方法来将其绘制到屏幕上 —— 此乃一个 GUI 工具的常见技术。我们将要创建一个叫做 gui
的库 crate,它含一个 GUI 库的结构。这个 GUI 库包含一些可供开发者使用的类型,比如 Button 或
TextField。在此之上,gui 的用户希望创建自定义的可以绘制于屏幕上的类型:比如,一个程序员可能
会增加 Image,另一个可能会增加 SelectBox。
这个例子中并不会实现一个功能完善的 GUI 库,不过会展示其中各个部分是如何结合在一起的。编写库
的时候,我们不可能知晓并定义所有其他程序员希望创建的类型。我们所知晓的是 gui 需要记录一系列
不同类型的值,并需要能够对其中每一个值调用 draw 方法。这里无需知道调用 draw 方法时具体会发
生什么,只要该值会有那个方法可供我们调用。
在拥有继承的语言中,可以定义一个名为 Component 的类,该类上有一个 draw 方法。其他的类比如
Button、Image 和 SelectBox 会从 Component 派生并因此继承 draw 方法。它们各自都可以覆盖 draw
方法来定义自己的行为,但是框架会把所有这些类型当作是 Component 的实例,并在其上调用 draw。
不过 Rust 并没有继承,我们得另寻出路。
Rust从入门到实战系列一百九十七:继承,作为类型系统与代码共享
最新推荐文章于 2024-06-24 09:50:45 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)