对象包含数据和行为
一本十分经典的编程书籍这么定义面向对象:
- 面向对象的程序是由对象组成的。一个对象包含数据和操作这些数据的过程。
按照这个定义,Rust是面向对象的:结构体 和 枚举包含数据,而 impl
实现了在其上的方法。虽然带有方法的结构体和枚举并不称为对象,但这与对象的功能是相似的。
封装——隐藏了实现细节
与其他面向对象语言一样,Rust 有封装的思想在里面。
只能通过对象上的公有方法来改变对象的数据。也可以用 pub
来改变数据的封装级别。
继承——作为类型系统与代码共享
继承——一个对象可以获得父对象的数据和方法,无需重新定义。
如果按照这个标准,Rust 并不是面向对象的。
但是 Rust 也提供了其他解决方案。
为什么使用继承?
- 重用代码:继承可以重用父类的成员和方法。而Rust其实也可以,第十章中,Trait的默认实现方法,只要任何实现了相同Trait的类型,都可以使用默认方法,也可以覆盖默认方法。
- 多态:子类型可以用于父类型可以使用的地方。Rust通过泛型对不同的类型进行抽象,并通过 trait bounds对类型添加约束。
不过最近,越来越多的人不再推荐继承,提出“组合大于继承”的说法。某些语言还只允许子类继承一个父类,进一步限制了继承的使用。
因为这些原因,Rust 选择使用 Trait 对象 而不是继承。接下来让我们看看,Rust中如何使用泛型和Trait对象实现多态。