继承和组合的一些思辨

以汽车为例,有两个子类:柴油机和汽油机;有两个组成部分:轮子和发动机。

父类与子类,整体与部分,可以以一棵树来表示,其中树根为父类(整体),树叶为子类(部分)。

父子关系,整体部分关系,看起来完全不同的概念,竟然有完全相同的拓扑结构。

最早的程序设计中,应该是没有父子关系的,而整体部分关系必须有。参考C语言里面的结构体和数组。结构体是固定数量,不同类型的部分;数组是不同数量,固定类型的部分。数组和结构结合起来就可以实现不同数量不同类型的部分。

那么父子继承关系是怎么出现的呢?我认为是人类思维的抽象,把相同的部分提取出来,形成一个父类。

自然界就是最好的研究素材。以狮子和豹子为例。在狮子眼里,豹子和自己没什么关系。假如草原上有一颗会思考的树,树发现狮子豹子和自己很不一样,他们都有嘴和脚,而自己没有,于是树抽象出一种有嘴有脚的生命,称之为动物。动物没有任何对应的实体,而狮子和豹子是真实存在的。可见,父子继承关系只是抽象,而整体部分关系却是真实存在的。

没有真实存在的继承关系竟然在人的思维中占有相当重的分量,我认为这是由于继承关系的压缩率高。很多时候,繁杂的整体部分关系抽象成继承关系后,具有很小的信息量,适合人类记忆、分析、交流。

比如我们要研究猫与狗的关系,如果我们知道一个是猫科一个是犬科,只要记住猫科和犬科的关系,80%的关系就找出来了。

程序设计和自然界非常不同。自然界是先有整体部分关系,然后抽象出父子继承关系;而程序可以先抽象出父子继承关系,然后通过具化子类来实现各个组成部分。

通过整体部分关系或者父子继承关系都可以完全描述清楚物体结构。组成结构和继承结构就如同信号处理里面的时域和频域,而对于波来说,用频域表示却有很大的便利性。

再说下滤波,就是在频域里面吧一些不关心的特征去掉,可以减少信息量,提高研究事物的效率。如果我们要研究狮子豹子的捕食能力,可以忽略嘴的长短而聚焦于嘴的咬合力,忽略腿的粗细而聚焦于腿的奔跑速度。

继承关系的压缩率高,但也不是没有缺点。相对组合来说,继承的结构太固化。继承也是把一些结构预植入人脑,从而来压缩信息。例如,一个交通工具的继承结构,轮船和汽车都继承自交通工具,新来一个既能在地上跑,又能在水里面游的交通工具,如果直接继承自交通工具,就很难利用汽车轮船的特征;或者采用多重继承,但是多重继承是不应该采取的。

有些领域很适合继承,比如ui;很多领域也适合组合,这个领域本身就是各个功能模块的组合,而各个功能模块之间耦合性很低。

组合和继承也是可以共存的,在不同的层次采用继承和组合。

通过接口继承可以平衡好继承和组合的关系,但是需要更丰富的领域经验。对于陌生的领域,可以优先使用组合,然后不断抽象演化,进而形成一个稳定的继承层次。这和研究自然界很类似。

posted on 2018-01-01 18:48  zhangshuliai  阅读(140)  评论(0编辑  收藏  举报