澳门新葡萄京官网注册 2

澳门新葡萄京官网注册Java中的继承与组合

正文首要表明Java中继续与重新整合的定义,以致它们中间的联络与分歧。首先小说会付出一小段代码示例,用于体现到底怎么是三番五回。然后演示如何通过“组合”来修正这种持续的统筹编写制定。最终总结这两边的运用处景,即到底应该选用继续依旧结合。

1、继承

设若大家有三个名称叫Insect(昆虫)的类,那几个类包涵五个办法:1)移动move(State of Qatar;
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();  //假设昆虫在攻击前必须要先移动一次
        System.out.println("Attack");
    }
}

前段时间,你想要定义叁个名字为Bee(蜜蜂)的类。Bee(蜜蜂)是Insect(昆虫)的一种,但贯彻了差别于Insect(昆虫)的attack(卡塔尔和move方法。当时大家能够用两次三番的宏图编写制定来落实Bee类,就像下边包车型客车代码相似:

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();
    }
}

InheritanceVSComposition作为三个测验类,在其main方法中生成了几个Bee类的实例,并赋值给Insect类型的援引变量
i。所以调用i的attack方法时,对应的是Bee类实例的attack方法,也正是调用了Bee类的attack方法。

类的延续布局图如下,极其简单:

澳门新葡萄京官网注册 1输出:

Fly
Fly
Attack

Fly被打字与印刷了五遍,相当于说move方法被调用了两回。但按理来说,move方法只应当被调用一回,因为无论昆虫照旧蜜蜂,叁次攻击前只移动一回。

澳门新葡萄京官网注册 ,题目出在子类(即Bee类)的attack方法的重载代码中,也便是super.attack(卡塔尔(قطر‎这一句。因为在父类(即Insect类)中,调用
attack方法时会先调用move方法,所以当子类(Bee)调用super.attack(卡塔尔国时,约等于也同期调用了被重载的move方法(注意是子
类被重载的move方法,实际不是父类的move方法)。

为了消除这么些题目,大家得以运用以下方法:

  1. 删去子类的attack方法。这么做会使得子类的attack方法的落到实处完全信任于父类对于该方法的实现(因为子类世袭了父类的attack方法)。假使父类的attack方法不受调整而发生了退换。举例说,父类的attack方法中调用了其它的move方法,那么子类的attack方法也会发出相应的变
    化,那是一种十分不佳的包装。
  2. 也足以重写子类的attack方法,像上边那样:

    public void attack() {
        move();
        System.out.println("Attack");
    }
    

如此有限援救了结果的不错,因为子类的attack方法不再依赖于父类。不过,子类attack方法的代码与父类爆发了再也(重复的attack方法会使得比相当多职业变得复杂,不独有是多打字与印刷了一条出口语句)。所以第三种艺术也极其,它不切合软件工程中有关心珍贵用的思考。

如此那般看来,世襲机制是有劣点的:子类重视于父类的落到实处细节,要是父类发生了改观,子类的结局将不堪设想。

2、组合

在上面的例子中,可以用结合的体制来替代世襲。大家先看一下利用组合怎么完结。

attack这一作用不再是四个艺术,而是被架空为一个接口。

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;
    }

    @Override
    public void move() {
        System.out.println(move);
    }

    @Override
    public 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类,它有着attack的效果与利益,所以它完成了attack接口:

// 这个封装类封装了一个Attack类型的对象
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();
    }
}

类图:
澳门新葡萄京官网注册 2

测量试验类代码,将AttackImpl的实例作为Attack类型的参数字传送给Bee类的布局函数:

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、何时该用世襲,什么日期该用组合?

以下两条标准表达了应该如何挑选继续与构成:

  • 设若存在一种IS-A的关联(举个例子Bee“是叁个”Insect),况且二个类要求向另三个类曝光全数的主意接口,那么更应有用三回九转的体制。
  • 比方存在一种HAS-A的关联(比如Bee“有八个”attack功用),那么更应有采用组合。

小结来说,世襲和构成都有她们的用途。唯有充足领略各目的和功力之间的关联,能力充足发挥这二种体制各自的独特之处。

参考:

  1.   Bloch, Joshua. Effective
    Java.
    Pearson Education India, 2008.
  2.   
  3.   http://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition–which-one-should-you-choose-.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注