复合优于继承

1. 继承破坏了封装性,换句话说,子类依赖于父类的实现细节。

 

需要进一步说明,这与方法调用不同,方法调用也依赖被调用的方法,但是并不依赖细节,也就是说,只要方法整体实现没有问题,方法调用就没有问题,但是继承很容易改变父类实现的细节(所以父类中能写成final尽量写成final),即使父类整体没有问题,也有可能因为子类细节实现不当,而破坏父类的约束。这使得继承具有脆弱性。

 

或者说,继承让子类很容易破坏影响父类的约束,父类约束的实现依赖子类的实现,并且,父类在他的后续版本中可以获得新的方法,而这个会对子类造成影响,虽然子类的代码没有变化,当初子类实现的时候也不知道未来的变化,显得很无辜。

 

Here, overriding is the root of evil.....

 

继承使得到的API限制在原始想重用的实现上,导致可变更性变差,限制了你的类的性能。

 

继承使得有了更多机会来暴露了类内部的细节,比如Properties p的例子,p.getProperty(String key),p.get(String key)。

 

继承很容易传播现有API内部的缺陷。

 

2. 为什么复合/转发在做到重用的同时,不会有上述问题?

a. 通过接口,抓住需要重用类的功能特性,同时还获得了灵活性,继承只能重用某一个具体类的代码,但复用利用接口,可以重用很多接口类的代码。

b. 组合模式,包装类,也正是利用了这一点,获得了灵活性。

c. 缺点:转发方法调用的性能影响(可以忽略),包装对象导致的内存占用(这个在敏感的地方显得很重要,因为复用会导致产生更多的对象。子类扩展属性的时候,如果继承的话,就只有属性本身内存的增加,如果复用的话,还需另外加一个属性宿主自身以及宿主引用的内存增加)

 

3. 什么时候用继承合适:当确实存在"is-a"关系的时候。

 

 

 

参考:

《Effective Java》第四章,第14条

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值