继承
-
继承是面向对象的三大特征之一(封装、继承、多态),也是实现软件复用的重要手段,继承是 “is-a” 的关系。
-
优点
- 代码复用
- 子类可以重写父类的方法
- 创建子类对象时,无需创建父类的对象,子类拥有父类的成员变量和行为。
- 子类在父类的基础上可根据自己的业务需求拓展
-
缺点
- 破坏封装
- 支持拓展,但往往以增加复杂度为代价
- 不支持动态继承,在运行时,子类无法选择不同的父类
- 紧耦合
当子类继承了父类,需要修改父类接口名称时,一旦修改,子类都会报错,后果不堪设想想。
组合
-
组合是一种较弱的关系,是 “has-a” 的关系
-
代码体现
/** * 组合 */ public class Animal { private void beat(){ System.out.println("心脏跳动..."); } public void breath(){ beat(); System.out.println("呼吸中..."); } }
/** * 组合 */ public class Bird { // 将Animal作为Bird的成员变量 private Animal a; public Bird(Animal a){ this.a = a; } public void breath(){ a.breath(); } public void fly(){ System.out.println("我在飞.."); } public static void main(String[] args){ Animal animal = new Animal(); Bird b = new Bird(animal); b.breath(); b.fly(); } }
-
优点
- 不破坏封装、松耦合
- 具有可拓展性
- 支持动态组合
-
缺点
- 整体类不能自动获得和局部类同样的接口
组合继承对比
组合 | 继承 | |
---|---|---|
是否会破坏封装 | 整体不能看到部分的内部实现细节,不会破坏封装 | 子类可以获得父类内部实现细节,破坏封装 |
是否支持动态 | 可支持动态组合 | 是单继承,不支持动态继承 |
是否实现多态 | 不可以实现多态 | 子类可以回溯父类,直到Object类,这样就可以根据业务实现多态(向上转型和向下转型) |
如何选择
- 当两个类之间存在明显的整体和部分的关系,则应该使用组合来实现复用
- 当我们需要对已有类做一番改造,从而得到新的符合需求的类,则应该使用继承
- 当需要被复用的类一定不会改变时,应该使用组合,否则,应该使用继承