澳门新浦京娱乐游戏Java中的继承与组合

澳门新浦京娱乐游戏 2

正文首要表明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();  //假设昆虫在攻击前必须要先移动一次
        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(State of Qatar时,也便是也还要调用了被重载的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
You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图