3.4.6 多重继承
到目前为止,所有示例都只有单一的继承链。换句话说,对于一个给定的类最多只有一个直接的超类。这不是必须的,在多重继承中,一个类可以有多个超类。
图3-10给出了一个多重继承设计。在此仍然有一个名为Animal的超类,根据大小将这个类进一步划分。此外根据食物划分了一个独立的层次类别,考虑移动方式又划分了一个层次类别。所有类型的动物都是这三个类的子类,如下所示。
|
| (点击查看大图)图 3-10 |
考虑用户界面环境,假定用户可以点击某张图片。这个对象好像既是按钮又是图片,因此其实现同时涉及了Image类和Button类的派生,如图3-11所示。
|
| 图 3-11 |
在某些情况下多重继承可能很有用,但是必须记住它也有很多缺点。许多程序员不喜欢多重继承,C++(www.cppentry.com)明确支持这种关系,而Java语言根本不予支持。批评多重继承是有原因的。
首先,用图形来表示多重继承十分复杂。如图3-10所示,当存在多重继承以及交叉线的时候,即使简单的类层次也会变得非常复杂。类层次结构的目的是让程序员更方便地理解代码之间的关系。而在多重继承中,类可以有多个彼此没有关系的超类。这么多类加入到对象的代码中,您真的能够跟踪发生了什么吗?
其次,多重继承能够破坏清晰的层次结构。在动物示例中,使用多重继承方法意味着Animal超类的作用降低,因为描述动物的代码现在被分成了三个独立的层次。尽管图3-10中的设计显示了三个清晰的层次,但是不难想象它们会变得如何凌乱。例如,如果您意识到所有的Jumper不仅以同样的方式移动,还吃同样的食物,该怎么办?由于层次是独立的,因此没有办法在不添加其他超类的情况下加入移动以及食物的概念。
第三,多重继承的实现很复杂。如果两个超类以不同方式实现了相同的行为,该怎么办?两个超类本身是同一个超类的子类,可以这样么?这种可能让实现变得复杂,因为在代码中建立这样复杂的关系对于作者以及读者而言都很困难。
其他语言取消多重继承的原因是通常应该避免使用多重继承。通过重新考虑层次或者使用第29章讲述的设计模式,在控制某个项目的设计时通常可以避免引入多重继承。