前言
最近看到effective java中提到“复合优于继承”,对这句话的真正意义不是很明白,通过整理相关资料进行了总结
一、什么是复合
官方解释是:不扩展现有的类,而是在新的类中增加一个私有域,引用现有类的一个实例。
二、什么是继承
继承来自于多个类中相同特征和行为的抽象,子类可以通过继承去调用父类的属性和方法,实现代码复用的目的,子类还可以扩展自己的属性和方法。举个例子:猫和狗都会呼吸、吃东西、都有性别,所以可以把它们抽象成小型动物,但是狗会看家、猫能捉老鼠,所以他们再分别实现看家和捉老鼠的方法。这样看来继承真的太强大了,很简单的实现代码复用。
三、为何还出现复合(组合)
现实中需求是多样和复杂的,经常出现各种变动,有些需求只用继承来实现就会出现一些问题。
如果我们想要游泳的能力可以继承鱼,如果想要奔跑可以继承兔子,如果我们又想奔跑还想游泳就不能通过继承来实现,因为只能单根继承,不能通过继承重用多个类中的代码。
还有就是一单继承就必须接受无论你是否愿意,如果想要飞行去继承鸟类,同时也继承身上长有羽毛的属性,造成了方法的污染,有些东西并不是我们想要的。
通过继承得到的方法是一种静态方法,不能动态的改变,例如从北京到上海如果继承飞机那么只能直飞过去,有可能中途需要到济南汉峪金谷打卡,对不起我们不支持。
所以针对继承的上述弊端,有人提出了另外的一种解决办法,使用聚合/组合来代替继承,这样不需要具备某些属性和方法,只要会借助具有某些属性和方法的其他事物就好了。
拥有一辆汽车可以愉快的畅游大草原。
想要在海里游可以使用各种轮船。
最重要的是你可以在运行过程中动态的切换交通工具。
2.复合/聚合示例
使用聚合/组合代码如下:
public class juheTest {
public static void main(String[] args) {
man jinanMan = new man();
jinanMan.changeAction(new car());
jinanMan.action();
jinanMan.changeAction(new ship());
jinanMan.action();
}
}
interface transPortation{
public void work();
}
class car implements transPortation{
@Override
public void work(){
System.out.println("汽车在陆地上飞驰");
}
}
class ship implements transPortation{
@Override
public void work() {
System.out.println("轮船通过狭窄的苏伊士运河");
}
}
/**定义一个人类,具有开轮船和开车的能力,并且可以按照需要更换交通工具
* */
class man{
//将transPortation作为一个私有属性添加进man中
private transPortation tp;
public void action(){
tp.work();
}
public void changeAction(transPortation tp){
this.tp = tp;
}
}
该处使用的url网络请求的数据。
总结
提示:
使用继承比较简单也很直观,判断是否适合用继承一种简洁办法是它们之间是否存在 is-a 的关系,否则使用组合/聚合。