在Effective Java中明确有提到一种思想就是组合优先于继承。实际中我们可以这样理解,组合是把代码摊开,而继承是把代码垒起来。很明显,摊开的代码更容易理解、扩展,耦合度更低。不过如果B类是A类的抽象,这时候继承更适用一点。
面对不同的场景,使用组合还是继承,需要看是has-a
还是is-a
关系。
来看对比示例:
class Animal{
private void beat(){
System.out.println("心脏跳动...");
}
public void breath(){
beat();
System.out.println("呼吸中...");
}
}
class Bird extends Animal{
//创建子类独有的方法fly()
public void fly(){
System.out.println("我是鸟,我在天空中自由的飞翔...");
}
}
class Wolf extends Animal{
//创建子类独有的方法run()
public void run(){
System.out.println("我是狼,我在草原上快速奔跑...");
}
}
动物都有心跳与呼吸,所以面对不同的动物,这是is-a关系,应该使用继承。
class 蔬菜{
public void 炒青菜(){}
}
class 水果{
public void 制作果盘(){}
}
class 汤{
public void 制作紫菜汤(){}
}
...
早中晚餐可以可以吃青菜、水果或者喝汤中的任意一种,这时候就应该用组合。
组合与继承的区别如下:
组合 | 继承 |
---|---|
has-a关系 | is-a关系 |
运行期决定 | 编译器决定 |
不破坏封装,整体和局部松耦合 | 破坏封装,子类依赖父类 |
支持扩展,随意增加组合类 | 只能继承一个父类,必须包含所有方法,增加系统复杂性 |
动态选择组合类方法 | 复用父类方法 |
网友评论