本节书摘来自华章出版社《面向对象的思考过程(原书第4版)》一书中的第1章,第1.11节,[美] 马特·魏斯费尔德(Matt Weisfeld) 著黄博文 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.11 组合
对象中包含其他对象非常自然。比如电视机包含开关和显示屏。计算机包含显卡、键盘和光驱。可以将计算机自身看成一个对象,而光驱也是一个有效的对象。
事实上,你可以打开计算机把光驱取下来放到你手上。计算机和光驱都可以看作对象。只是计算机包含其他的对象(譬如光驱)。
使用其他对象来构建或结合成新的对象,这种方式就是组合。
1.11.1 抽象
和继承一样,组合也是一种构建对象的机制。事实上,我想说只有两种方式来使用其他类构建新类,这两种方式就是继承和组合。之前已经看到了,继承允许类继承另一个类。我们可以把属性和行为抽象到通用类中。例如,狗和猫都是哺乳动物,因为狗是(is-a)哺乳动物,猫也是(is-a)哺乳动物。而使用组合,我们也可以把类嵌入其他类中来构造新类。
我们可以拿车和引擎之间的关系来举例。把引擎从车中分离出来是明显可行的。我们可以单独构建引擎,把它用到各种车上,更别提还有其他优势。但我们不能说引擎是(is-a)一辆车。顺口说出来我们就觉得不对(因为我们在为真实世界的系统建模,这正是我们想要的效果)。我们最好用has-a术语来描述组合关系。车有(has-a)引擎。
1.11.2 has-a关系
我们之前已经讨论过了继承关系是is-a关系的原因,而组合关系可以称为has-a关系。我们可以使用上一小节中的例子,电视有(has-a)开关和显示屏。电视显而易见不是一个开关,所以两者没有继承关系。同样,计算机有(has-a)显卡,有(has-a)键盘,有(has-a)光驱。第7章深入讲解继承和组合这两个主题以及相互之间的关系。