OOP中的继承

继承的好处


  • 代码复用:继承父类以后,子类不需要再次编写相同的代码,却能获得和父类相同的行为和数据,多好!简直是空手套白狼,无本万利的事情嘛!另外,要知道维护一份代码与维护两份乃至好几份相同的代码,这两种感受简直天壤之别!
  • 定制、差异化:
    • 覆盖父类原有行为:你还可以重写某些父类方法,使其名字虽然和父类的方法名一样,但是执行的内容却完全不同,是不是很神奇!
    • 新增行为和数据:除了以上,你还可以增加父类从来没有的东西:可以是行为或者数据,以使子类在某些方面看上去,与父类完全不同,体现出真正的差异化!

“型态”为主,而不是“行为”


虽然继承确实能够带来代码复用的好处,但是通常来说,它却不是发挥代码复用功能的最佳方式,大量的实践证明最佳方式通常是组合

这也不是说继承就毫无用武之地了,就像小标题表述的那样,现今面向对象程序设计中,继承并非以继承类别的“行为”为主,而是继承类别的“型态”,使得组件的类型一致,从而易于编写通用代码。

继承往往容易被过度使用


现在要解决一个问题:

  • 问题很简单,可能几行代码就足够了。
  • 也可能稍微复杂,要写一个或几个方法来解决它。
  • 也可能相当复杂,可能需要概括一个抽象概念以写出一个类来处理。
  • 甚至问题的规模相当之大,需要数个类相互协作,而类与类之间可能还需要构成某种层次结构。

针对不同规模的问题,作为一个合格的软件工程师,我们也要懂得如何选取不同口径的武器来解决它。而继承,在面向对象设计领域中算是一个重量级、大口径的武器了。所以,除非你确定这是一个复杂度相当大的问题,否则请不要轻易掏出继承这把大口径武器。

滥用继承的危害


类层次结构演变的越深越宽,引发的问题就越致命。一个类越是在类层次结构中越深的地方,就越难理解、维护及修改。因为要理解一个,就需要理解其所有父类。例如,在子类中修改一个看似无害的虚函数,就可能会违背了众多父类中某个父类的假设,从而产生微妙又难以找到的bug。