好,除了在泛化关系和这个
委托的时候存在一些容易混用的这种情况,不太适合的混用,
这个二者这种,这个设计方案之外呢, 本身泛化关系也有一些滥用的情况,我们举一些例子。
比如说这个例子中,这个飞机,这个
机翼和机身,机尾,引擎它们之间构成一种泛化关系,那这是不合适的。
那它们之间是一种什么呢?非常这个明显是一种组合关系,
它这里边为什么这个将它这个变成一种泛化关系呢?
那是因为它有一定的功利性的这个目的,就是说它比如说搞一个游戏,是吧,这个飞机呀,
可以这个机翼呀,机身啊,机尾,这个引擎都是可以换的,是吧,借了些什么东西之后,然后
它这个机身呀,机翼都可以变形,变换,一种机身隐身呀,由大变小,由小变大的,是吧,
这时候呢如果用这种方案的话,它们都飞行,是吧,其实它这个飞机就是一些
机身啊,机翼,机尾都跟着飞机一块飞,这个它们都有飞行的这么一个操作, 这时候呢如果这样的话它这样
是一个比较省事的一种情况,这样的话呢就不 需要写一句代码,直接继承过来之后,它们都跟着飞,这样的话就
很好的实现这个功能,但是这有什么问题?就是它不符合自然的思维方式,这个还是需要用这- 个什么呢,
要用这个委托这种方式来进行 描述。
另外一种反过来也不行,反过来呢主要是这个
认为飞机就是一个机翼,机身,机尾,引擎,好像是一个关系,
但实际上呢,这种这个作用方法的时候要各位注意,是吧,它是 飞机是一个这个
机翼和机身和机尾和引擎,这是一个不严格的这个 描述,正确的这个描述应该是飞机是由一个机翼
机身,机尾,引擎组成的,这样的话就不会出现这个问题。
这个另外呢就是还有需要
注意的就是说这个熊和熊猫,我们知道熊猫它是一种 是个熊科,一种这个动物,
它是一种熊,这是毫无疑问,但是很多的一些同学可能对这个
不太这个了解,是吧,认为熊猫 这个不是一种熊,熊猫是一种熊,是浣熊类的东西。
本身熊猫是一种肉食性动物,只不过后来条件
限于条件,没有肉吃,它就开始吃竹子, 所以它本身是一种熊,这是对的。
但是 它和濒危物种之间,它是不是一种濒危物种?这个就需要考虑, 这其实用到我们前面讲到幂类型的问题,
是吧,就是物种来说,濒危物种的实例是什么?濒危物种实例比如说是熊猫,
是什么金丝猴,什么这个扬子鳄,这个什么白鳍豚,等等, 但是这个熊猫的实例是什么?
熊猫的实例这个什么,什么盼盼,什么圆圆,团团什么,这是熊猫的实例,它们二者是一个
不是一回事,就是一个是这个集合,一个是实例,因此它们二者
不能构成一种泛化关系,真正的这个泛化应该是下面这样子,
是吧,物种范围,这个濒危物种是一种特殊的物种,但是一个物种
呢,是一种幂类型,它对应,它与真正的那个动物的那个
类,构成一种一对多的关系,这个我们前面也提到过,这样的方式是对的。
就是说这个就是说提示大家呢,在这个真正这个建立泛化关系的时候呢,
一定要考察一些泛化关系的这个实例,这个各种类的实例,有的时候它的实例
有些时候并不是一种这个一个层次上的事, 有些时候它是有的实例正好是另外的一个类,这个时候你需要这个就
建立这种,不要建立泛化关系,而建立关联关系。
还有一种情况呢也是一个复用的一个例子,是吧,就是说我们在房间
在房间的时候呢,我们这个为了计算这个房间的容积, 我们为了这个复用,是吧,因为这个现在有个立方体,立方体可以计算容积,
这时候我们在这个房间,然后直接继承立方体,这样行不行呢?是吧,
这时候这个,当然这个从功利性的角度来看呢,
它是可以计算容积,直接继承下来,然后呢就可以无条件的
具有了计算容积的这种方法,但是呢由于立方体有拉伸旋转的这个操作,是吧,
你可以不用,在当前的房间里面不用,但是你保不齐别人会用,别人一旦用的时候你就会
对你的房间啊,产生破坏性的后果,是吧,你房间不能动,你一拉伸,一旋转,那就
完全这个房间就错了,本身就是造成一些功能性的一些问题。
在现实世界中,那就意味着这个房间是被这个 毁坏,是吧,造成车毁人亡这种事故,
这是不行的,这是跟我们前面的例子很像。
那反过来继承呢更不行,是吧,因为本身呢这个 立方体呀,圆柱体呀,这些东西我们没法找到它的源代码,
即使我们有它的源代码,我们也不能有改写这个源代码的权利,用这种方式
完全是这个不可能实现的。
第一种情况呢就是说这个,还有一种问题就是说 如果说这个圆柱体,是吧,当然也有一些圆柱体的房间,但是这时候呢
一旦形成这种多重关系的话,是吧,这个房间到底是什么形状这就 非常困惑。
所以正确的方案呢应该是对于这种情况呢,即如何
既这个复用了已经存在的一些类的一些功能,然后呢我们又不会这个造成很大的一些
风险,或者说是一些这个 自然这种,对我们这种自然思维方式产生一定的这个危害,这怎么办呢?
这时候用这种方案,是吧,建立关联关系,房间和这个
三维图形,或者说是它的父类也找到了,然后建立,其实也就是这个
跟这个立方体和这个圆柱体建立关联关系,然后计算体积,这写一个计算容积,
然后呢它可以通过一个委托关系一句话来访问,这样的话呢就可以屏蔽掉一些
没有用的一些这个拉伸啊,旋转这个我只要不
对它进行这个,这个 委托,不建立这种,在我房间里边不提供拉伸旋转接口,
那么别人调用的时候就没法调用,这样的话就安全了,这个跟前面我们讲的非常相似。
还有一个多重复用的一些误用的一种情况, 比如说我们现在举一个例子,就是说这个
现在是有两种颜色按钮已经存在了,在我们这个可复用的资产中,一个叫颜色按钮,
什么是颜色按钮呢?这个颜色按钮呢是这个
这个,只涂色, 就是可以有一个颜色,红橙黄绿,然后呢可以给它
点击一个涂色的方法,就是给它从红色变成蓝色啊,是吧, 根据当前的颜色给它再重新涂一遍。
另外一个变形按钮,就是这个按钮呢 可以改变形状,是圆形,椭圆,
三角形,正方形,弧状,矩形,等等,还有不规则形都可以变换,则个形状有一个枚举
类型的这个属性来负责,然后一旦变形的时候就根据当前的形状来变成 这个形状。
这两个都是这个不同的按钮,都已经在我们的这个 复用的这个资产里边已经存在了。
现在我们,现在有一个新的需求就是想让它既改变颜色,
又可以改变形状,改变这个按钮,现在有人想呢,搞一个方案,想用这个
泛化关系,多重泛化关系来实现,这个大家考虑行不行?
实际上呢这个问题,实际上呢是一个非常复杂的 问题,行不行呢,不好这个
简单的说行还是不行,在某些条件 这个存在的情况下,它是可能的,
在某些条件不存在的情况下呢是不行的,什么条件呢?
就是说这个泛化关系说白了其实是一种组合关系,
你不要,它无非就是把两个父类的一些所有特征给它们
混到一块,这个你不要对它寄望这个非常高的要求,
但是如果说是在一些条件特殊的情况下,也保不齐会产生一些增量,
这个一些这个惊喜。
比如说 这里呢实际上你这个彩色变形按钮,就是既变
颜色,然后呢又变形状,并且变形状的时候,
这个涂的颜色跟那个变形的那个形状正好是相符合的。
是吧,不能你这个 既这个从这个颜色,是吧,涂红色,是吧,我这个
彩色按钮本身就是涂一个矩形,但是这个变形之后再涂颜色的时候,这个它是根据我,
它非常智能的根据我这个形状的不同,它涂这个不同的形状,这是不是可能?
这点其实呢我们这个可以考虑,这个在C++
中确实有这种方案,但是这是非常特殊的情况,一方面呢就是
首先呢,如果单纯从这种方案来说是很 不太可能成功的,因为它的这个涂色的这个
这个大小,然后它的这个按钮的坐标值,这完全是两套,
是吧,它在这边画颜色,在那边呢画形状,这是完全两套 x,y,这样的话它没法拧到一块,是吧,这个是不行的。
但是一旦我们如果说它们在彩色按钮之上, 然后呢建了一个一般的这个按钮,这个
按钮这个x,y,然后彩色按钮和变形按钮都继承这个 更高级的这个,更抽象的这个按钮的这个
情况下,这时候可能会成功,就是这时候当然得用C++中非常特殊的一种继承关系,就是
虚拟继承,虚拟继承的话,所有的这些它 这个,它爷爷,爷爷这个类里边的这些
属于爷爷类的共性,定义里边共性的一些这个x,y的这些属性,
继承到孙子这儿呢,全部都变成一套,而不是两套,这样的话呢就有可能会实现,
因为它们都,它们的x,y坐标啊是一样,它们在涂色和这个画 形状的时候都是在相同的一个坐标点上画,那是可能的。
但是即使这样呢, 还不行,还得这个涂色的时候不是一种这个非常机械的涂色,
而是找到一个图形的中间的一个点,然后进行渲染的这种方式,是吧,
这时候就可以了,你这个不是直接画,渲染一个 这个画一个矩形,而是找到这个图形中间点,然后呢
调用它的渲染的这个操作,这样的话它就是相当于在一点上这个生发开去,只要碰到一些
闭合的边界,它就会自动停止。
这样的话你这个涂色 它根据现在是个矩形就涂个矩形,现在是个三角形就涂个三角形,是吧,
现在是个圆形就涂个圆形,如果这样条件满足的话,这个就是可能的, 否则它就不可能。
所以, 总而言之,在多重继承的时候,我们不要对它抱有希望,但是呢
保不齐有的情况会给我们一些惊喜,就是这种情况,是吧,我们一句代码不写,我们
白捡了一个功能,这体现了这个系统的这个,也是很有意思的地方,就是这个系统的这个- 有限性,
这个如果解释这个问题其实又得回到我们一开始给大家讲到的这个系统,什么是系统?这个概- 念上来说,
是吧,它们互相融合,发生信息交换就会产生新的功能,是一种好的系统。