首先,我们来看一看继承的好处。
设计一个鸭子类Duck:
public class Duck {
public Duck() {
System.out.println("i an a duck");
}
public void fly(){
System.out.println("飞");
};
public void swim(){
System.out.println("游泳");
}
public void quack(){
System.out.println("ga~ga~ga");
}
public void display(){
System.out.println("描述一下自己");
}
}
现在有个子类绿头鸭GreenHeadDuck:
public class GreenHeadDuck extends Duck {
public GreenHeadDuck() {
System.out.println("I am a greenHeadDuck");
}
public void head(){
System.out.println("我的头的绿的。。。。。。");
}
@Override
public void display() {
System.out.println("我是绿头鸭");
}
public void display(String name) {
System.out.println("我叫" + name);
}
}
继承的好处就是,可以重写父类的方法display(),也可以重构父类的方法display(String name),也可以另外写自己的实现head(),都不影响。
现在设计另外一个子类:玩具小黄鸭BathDuck():
问题来了,小黄鸭会叫,但是小黄鸭不会飞,所以对BathDuck来说,fly()方法是无用的,多余的,但是继承规定了子类会继承父类所有的方法。这时候就要用组合。组合可以简单的理解成“有一个”。具体看代码。
看Duck类:
public class Duck {
public void fly(){
System.out.println("飞");
};
public void swim(){
System.out.println("游泳");
}
public void quack(){
System.out.println("ga~ga~ga");
}
public void display(){
System.out.println("我是一只鸭子");
}
}
Duck类几乎不变的,看看BathDuck类:
public class BathDuck {
private Duck duck;
public BathDuck(Duck duck) {
this.duck = duck;
}
public void display() {
this.duck.display();
}
public void swim(){
System.out.println("我只我会浮在水面上,风往哪吹,我往哪游!!");
}
}
对于自己不需要的方法,完全就不会加载进来,需要的可以用Duck对象去调用duck的方法。将父类变成一种属性,这个就是“有一个”属性。谁需要谁就用引进这个属性,
GreenHeadDuck:
public class GreenHeadDuck {
private Duck duck;
public GreenHeadDuck(Duck duck) {
this.duck = duck;
}
public void display() {
duck.display();
}
}
这就是最简单的组合的例子。
继承要慎用,其使用场合仅限于你确信使用该技术有效的情况。一个判断方法是,问一问自己是否需要从新类向基类进行向上转型。如果是必须的,则继承是必要的。反之则应该好好考虑是否需要继承。《Java编程思想》
只有当子类真正是超类的子类型时,才适合用继承。换句话说,对于两个类A和B,只有当两者之间确实存在is-a关系的时候,类B才应该继续类A。《Effective Java》
还有其他组合的例子会在后续列举。