继承VS组合
来源:互联网 发布:中国项目数据分析师网 编辑:程序博客网 时间:2024/04/29 21:24
本文展示了Java中继承和组合的概念。首先给出一个继承的例子,然后给出如何使用组合来改进继承的设计。最后总结了如何在继承和组合之间做选择。
1.继承
假设我们有一个Insect类。这个类包含两个方法:1)move()和2)attack()。
class Insect {
private int size;
private String color;
public Insect(int size, String color) {
this.size = size;
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void move() {
System.out.println("Move");
}
public void attack() {
move();
//assuming an insect needs to move before attackingSystem.out.println("Attack");
}
}
现在你打算定义一个Bee类,它是一种Insect,但是attack()和move()有不同的实现方式。这可以通过使用类似下面的继承的设计来实现。
class Bee extends Insect {
public Bee(int size, String color) {
super(size, color);
}
public void move() {
System.out.println("Fly");
}
public void attack() {
move();
super.attack();
}
}
public class InheritanceVSComposition {
public static void main(String[] args) {
Insect i = new Bee(1, "red");
i.attack();}
}
类的层级图很简单:
输出:
Fly
Fly
Attack
“Fly”打印了两次,说明move()被调用了两次。但是它应该只被调用一次。
问题是由super.attack()方法引起的。Insect的attack()方法调用了move()方法。当子类调用super.attack()时,它同样调用被重写的move()方法。
要来修复这个问题,我们可以:
- 取消子类的attack()方法。这将使得子类依赖超类的attack()的实现。如果超类中的attack()方法在之后被改变了(这超出了你的控制),比如,超类的attack()方法使用了另一种方法来移动,子类也将需要被改动。这是一种坏的封装。
- 像下面一样重写attack()方法:
public void attack() {
move();
System.out.println("Attack");
}
这会保证正确的结果,因为子类不再依赖超类。然而,这个代码复制了超类的代码(想想如果attack()做很复杂的事而不仅仅只打印一个字符串)。这不符合软件工程的重用原则。
2.组合
代替继承,组合在这种情况下可以被使用。让我们首先看一下组合的解决方案。
Attach 函数被抽象为一个接口。
interface Attack {
public void move();
public void attack();
}
不同类型的attack可以通过实现Attack接口来定义。
class AttackImpl implements Attack {
private String move;
private String attack;
public AttackImpl(String move, String attack) {
this.move = move;
this.attack = attack;
}
@Overridepublic void move() {
System.out.println(move);
}
@Overridepublic void attack()
{
move();
System.out.println(attack);
}
}
因为attack函数被提取出来了,Insect不再做任何与attack相关的事情。
class Insect {
private int size;
private String color;
public Insect(int size, String color) {
this.size = size;
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
Bee是一种Insect,它可以攻击:
// This wrapper class wrap an Attack object
class Bee extends Insect implements Attack {
private Attack attack;
public Bee(int size, String color, Attack attack) {
super(size, color);
this.attack = attack;
}
public void move() {
attack.move();
}
public void attack() {
attack.attack();
}
}
类图:
public class InheritanceVSComposition2 {
public static void main(String[] args) {
Bee a = new Bee(1, "black", new AttackImpl("fly", "move"));
a.attack();
// if you need another implementation of move()// there is no need to change Insect, we can quickly use new method to attack Bee b = new Bee(1, "black", new AttackImpl("fly", "sting"));
b.attack();
}
}
输出:fly
move
fly
sting
3.什么时候使用哪一个呢?
下面的两条可以指导如何在继承与组合之间做选择:
1.如果是IS-A关系,并且类想向另一个类暴露所有的接口,继承是可选的。
2.如果是HAS-A关系,组合是可选的。
总的来说,继承和组合都有他们的使用,理解它们的相对优点是值得的。
参考:
1. Bloch, Joshua. Effective java. Pearson Education India, 2008.
2. http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance
3. http://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition--which-one-should-you-choose-.html
原文:
http://www.programcreek.com/2014/05/inheritance-vs-composition-in-java/
- 继承VS组合
- 十一、组合 VS 继承
- Exercise 44: 继承 vs 组合
- Java学习10:继承VS组合
- 面向对象第十一课,继承,继承VS组合
- Rhyme/StudyNote Java 继承VS组合,什么时候用继承、什么时候用组合?
- 知识点---(组合(Composition)VS (inheritace)继承)
- React.js 官方资料摘记:组合 VS 继承
- 继承 组合
- 组合 继承
- 继承、组合
- 组合继承
- 组合、继承
- 组合 继承
- JS继承--组合继承
- JavaScript 继承---组合继承
- JAVA菜鸟入门篇 - 继承VS组合、final关键字 (十六)
- js继承之-----组合继承
- uva 1218 Perfect Service 树形dp
- memcached性能测试 twemperf
- 安卓开发之 Intent的介绍
- Hive 中如何使用符合数据结构 maps,array,structs
- UIslider滑块大小
- 继承VS组合
- Cannot load 32-bit SWT libraries on 64-bit JVM,SDK Manager不能启动。
- Python 多线程
- android 版本升级时,so变化
- NYOJ-123-士兵杀敌(四)【线段树】
- C语言函数指针基础
- springmvc mybatis 整合 框架源码 bootstrap html5 mysql oracle spring
- 节点的nodeName与nodeValue
- 51nod 算法马拉松7 B.选数字