如果你是个不喜欢看细节的人,这篇文章主要说两点:
正文 面向对象设计里有一个原则叫组合复用原则(Composition/Aggregate Reuse Principle, CARP),是说尽量使用对象组合,而不是继承来达到复用的目的。 从语言支持来看,C++支持继承多重继承,Java只支持单继承,Golang不支持继承。 继承好像很不被待见。 但在日常中工作,还是经常看到滥用继承的情况,造成了不必要的复杂性和不灵活。本文打算说说我看到的继承设计的问题。 复用 据我观察,大多数BUG都来自不合理的复用,分为两种情况:
继承和组合是复用的两种最基本的方式。可以从三方面理解复用的好处:
理由一: 继承更不好理解 继承的复用是隐式的,组合是显示的。继承不仅复用逻辑,还复用状态。组合一般会给复用的对象起个名字,有助于理解。对于支持多重继承的语言来说,如果设计成菱形继承关系,就更坑了。 理由二: 继承容易滥用,破坏封装 和组合相比,继承容易被滥用为“白盒”复用,破坏封装性。 来看个具体的例子(用python描述): 从这个例子中可以看到几个问题:
理由三: 继承更不灵活 除了被子类依赖的实现不能随意调整,继承不够灵活还体现在以下几方面:
怎么合理使用继承? 继承是面向对象设计的三大特性之一,只是其太容易被滥用,导致很不受待见。不过,我们还是在很多设计里看到其身影,特别是客户端相关库的设计,比如Java Swing的JComponent系列,Android的View系列,iOS的UIView系列等,Android的Activity机制也是通过继承来定义生命周期管理的,这些设计有共同的特点:
事实上,虽然我们很多时候继承这些类,但我们基本不用关心这些类的实现。在我们自己进行继承设计时,遵从这些约束,也会产出更高质量的设计。 欢迎通过评论分享你的观点,进行更多讨论 :) |
|
来自: richard_168 > 《待分类》