现在的位置: 首页 > 综合 > 正文

※C++随笔※=>☆C++基础☆=>※№ 浅谈组合与继承的关系

2014年06月04日 ⁄ 综合 ⁄ 共 2365字 ⁄ 字号 评论关闭

概述

        由现有的类生成新的类,有两种方法就是组合与继承。我们把UML中的关联关系和聚集关系统称为组合关系。组合与继承都是提高代码可重用性的手段。在设计对象模型时,可以按照语义来识别类之间的组合关系和继承关系。在有些情况下,采用组合关系或者继承关系能完成同样的任务,组合和继承存在着对应关系:组合中的整体类和继承中的子类对应,组合中的局部类和继承中的父类对应。

        组合一般是将现有的类型作为新类型底层实现的一部分来加以复用,在一个类中引用另一个类。而继承是拥有了父类的非私有方法。其中“is-a (是一个)”的关系是用继承来表达的,而“has-a(有一个)”的关系则是用组合来表达的。但在抽象问题的阶段,我们如何去准确把握什么时候用组合,什么时候用继承就成了问题。
        网上有个很有意思的比喻:
                继承是说“我父亲在家里给我帮了很大的忙”。 
                组合是说“我请了个老头在我家里干活”。
       换个角度:
                继承复用接口
                组合复用类


组合VS继承

    组合
        对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。
    继承
        类继承允许你根据其他类的实现来定义一个类的实现。这种通过生成子类的复用通常被称为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,父类的内部细节对子类可见。
        VS
        继承和组合各有优缺点。类继承是在编译时刻静态定义的,且可直接使用,因为程序设计语言直接支持类继承。类继承可以较方便地改变被复用的实现。当一个子类重定义一些而不是全部操作时,它也能影响它所继承的操作,只要在这些操作中调用了被重定的操作。但是类继承也有一些不足之处。首先,因继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现。更糟的是,父类通常至少定义了部分子类的具体表示。因为继承对子类揭示了其父类的实现细节,所以继承常被认为“破坏了封装性”
。子类中的实现与它的父类有如此紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。
    
        当你需要复用子类时,实现上的依赖性就会产生一些问题。如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。一个可用的解决方法就是只继承抽象类,因为抽象类通常提供较少的实现。对象组合是通过获得对其他对象的引用而在运行时刻动态定义的。组合要求对象遵守彼此的接口约定,进而要求更仔细地定义接口,而这些接口并不妨碍你将一个对象和其他对象一起使用。这还会产生良好的结果:因为对象只能通过接口访问,所以我们并不破坏封装性;只要类型一致,运行时刻还可以用一个对象来替代另一个对象;更进一步,因为对象的实现是基于接口写的,所以实现上存在较少的依赖关系。

        对象组合对系统设计还有另一个作用,即优先使用对象组合有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。另一方面,基于对象组合的设计会有更多的对象 (而有较少的类),且系统的行为将依赖于对象间的关系而不是被定义在某个类中。


        组合关系和继承关系相比,前者的最主要优势是不会破坏封装,在软件开发阶段,组合关系虽然不会比继承关系减少编码量,但是到了软件维护阶段,由于组合关系使系统具有较好的松耦合性,因此使得系统更加容易维护。组合关系的缺点是比继承关系要创建更多的对象。从软件构架来说,组合,耦合度比继承弱,继承是对父类方法和数据成员的兼收并蓄,而组合,可以有选择得使用某一种方法。
        于是,我们得到了一个小的结论。"组合优越继承" Favor Composition Over Inheritance


实战

        在开发过程中,我们经常滥用继承。如在游戏开发中,我们会有很多种职业。OK,先抽象各个职业。作为基类,然后再继承为各个职业。
        
        然而,现在有新的需求了,每个职业现在都分有种族了。于是,我们继续继承。类成倍增长
        
        哪天,又有新的需求,每个职业又分为风、火、雷、水、土属性。于是....., 哪天又有新的需求..... 最终发现无法维护。
        上述例子,就是典型的滥用继承了,导致了类的几何倍数增长。这在开发中是不可取的,也是不推荐的。这个有点类似于设计模式中的Bridge模式。有时间的话,我会写Bridge模式的用法及原理详细描述下。
        Bridge模式

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以后的笔记潇汀会尽量详细讲解一些相关知识的,希望大家继续关注我的博客。
本节笔记到这里就结束了。

潇汀一有时间就会把自己的学习心得,觉得比较好的知识点写出来和大家一起分享。
游戏开发的路很长很长,非常希望能和大家一起交流,共同学习,共同进步。
如果文章中有什么疏漏的地方,也请大家指正。也希望大家可以多留言来和我探讨编程相关的问题。
最后,谢谢你们一直的支持~~~

                  

抱歉!评论已关闭.