组合还是继承

如题,每天在“面向对象”的我们,也常常遇到这个选择吧。刚好看书书读到这个话题,就记录下阅读的理解。

继承要慎用,其使用场合仅限于你确信使用该技术有效的情况。一个判断方法是,问一问自己是否需要从新类向基类进行向上转型。如果是必须的,则继承是必要的。反之则应该好好考虑是否需要继承。
——《java编程思想 第四版》 p140

复合优于继承 与方法调用不同的是,继承打破了封装性。换句话说,子类依赖于其超类中特定功能的实现细节。

只有当子类真正是超类的子类型时,才适合用继承。换句话说,对于两个类A和B,只有当两者之间确实存在“is-a”关系的时候,类B才应该继续类A。

为了避免这种脆弱性,可以用复合和转发机制来代替继承,尤其是当存在适当的接口可以实现包装类的时候。包装类不仅比子类更健壮,而且功能也更加强大。

——《Effective Java》 item.16

在平时工作过程中,我自己也是更多选择组合而不是继承。但也没有个明确清晰的判断标准。和同事交流时,虽然也推荐多用组合,但也说不出个具体的缘由。平时主要是开发android app,在UI部分的代码里,自己也是大量使用组合,譬如view的复用,一些逻辑部分也是可以通过建一个xxxController,xxxManager来复用。减少Activity,Fragment内的代码量。

之前遇到过项目里的一个情形,几个类似布局的页面,实现是共同继承了一个基类。但这个基类并没有任何地方直接引用到,即项目内没有子类向上转型的地方。我认为仅仅是为了代码复用,是完全不需要继承的,把代码提到一个新类中,组合使用即可。后来这些页面之间由于需求问题,开始有更多的地方不同了,如果是在继承的情况下,改动起来反而更加复杂。因为不能轻易的去修改基类,可能会影响到其他页面。组合可以更灵活,我可以有选择的复用共同的部分,而自己继续写不同的地方,不会一股脑的继承了所有基类的细节,不用去考虑基类里的具体细节。