inheritance中文Java语言_Inheritance vs. Composition in Java

This article illustrates the concepts of inheritance vs. composition in Java. It first shows an example of inheritance, and then shows how to improve the inheritance design by using composition. How to choose between them is summarized at the end.

1. Inheritance

Let's suppose we have an Insect class. This class contains two methods: 1) move() and 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 attacking

System.out.println("Attack");

}

}

Now you want to define a Bee class, which is a type of Insect, but have different implement ations of attack() and move(). This can be done by using an inheritance design like the following:

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

}

}

The class hierarchy diagram is as simple as:

0ccf481e2a781c1d29c10a649a9f9dfb.png

Output:

Fly

Fly

Attack

"Fly" was printed twice, which indicates move() is called twice. But it should be called only ONCE.

The problem is caused by the super.attack() method. The attack() method of Insect invokes move() method. When the subclass calls super.attack(), it also invokes the overridden move() method.

To fix the problem, we can:

eliminate the subclass's attack() method. This will make the subclass depends on the super class's implementation of attack(). If the attack() method in the super class is changed later (which is out of your control), e.g., the super class's attack() method use another method to move, the subclass will need to be changed too. This is bad encapsulation.

rewrite the attack() method like the following:

public void attack() {

move();

System.out.println("Attack");

}

This would guarantee the correct result, because the subclass is not dependent on the superclass any more. However, the code is the duplicate of the superclass. (Image attack() method does complex things other than just printing a string) This does not following software engineering rule of reusing.

This inheritance design is bad, because the subclass depends on the implementation details of its superclass. If the superclass changes, the subclass may break.

2. Composition

Instead of inheritance, composition can be used in this case. Let's first take a look at the composition solution.

The attack function is abstracted as an interface.

interface Attack {

public void move();

public void attack();

}

Different kinds of attack can be defined by implementing theAttackinterface.

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

}

}

Since the attack function is extracted,Insectdoes not do anything related with attack any longer.

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 is a type of Insect, it can attack.

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

}

}

Class Diagram:

34f2309a15415f56460c245e2a1988c4.png

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. When to Use Which?

The following two items can guide the selection between inheritance and composition:

If there is an IS-A relation, and a class wants to expose all the interface to another class, inheritance is likely to be preferred.

If there is a HAS-A relationship, composition is preferred.

In summary, Inheritanceand composition both have their uses, and it pays to understand their relative merits.

References:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值