继承or组合

在java中,组合和继承都允许在新的类中放置对象,组合是显式地这么做,而继承呢是隐式地做。那么问题来了,如何在这两种技术中选择一种呢?下面我就来介绍一下这两种技术各自的优势。
继承的威力
继承是JAVA的三大特性之一。使用extends关键字,导出类就能获得基类中所有的域和方法,从而达到复用代码的目的。但这并不是继承技术中最重要的方面,其最重要的方面是用来表现新类和基类的关系。这种关系可以用“新类是现有类的一种类型”这句话加以概括。举个好理解的例子,风笛是“继承”自乐器,那么风笛自然就是乐器的一种了。
可能有人要问了,为什么这种关系是继承的精髓呢?因为四个字—向上转型。下面我们结合代码来理解一下向上转型。

class Instrument{
    public void play(){}
    static void tune(Instrument i){
    i.play();
    }
}

public class Wind extends Instrument{
    public static void main(String[] args){
        Wind flute = new Wind();
        Instrument.tune(flute); //向上转型
    }
}

仔细观察这段代码,会发现很有意思,main函数里调用了Instrument的tune方法,入参居然不是Instrument的类型,但是这里运行之后发现居然没报错,要知道JAVA是强类型语言,对类型的检查非常严格。所以这里应该是合理的,合理的地方在于,Wind继承了Instrument,自然而然,Wind的类型就是Instrument,所以不会报错。这就是“向上转型”。
那么可能又要有人问了,向上转型又如何,有什么用呢?好的,接下来我就来改造一下代码。

class Instrument{
    void play(){System.out.println("playing instrument~");}
    static void tune(Instrument i){
        i.play();
    }
}

class Brass extends Instrument{
    void play(){
        System.out.println("playing brass~");
    }
}

public class Wind extends Instrument{
    void play(){
        System.out.println("playing Wind~");
    }
    public static void main(String[] args){
        Wind flute = new Wind();
        Brass brass = new Brass();
        Instrument.tune(flute); //向上转型
        Instrument.tune(brass);
    }
}
///:playing Wind~
///:playing brass~

可以看到,通过向上转型调用Instrment的tune方法,i.play()中的play调用的居然是其子类对应的方法,也就是说:

不同对象的上转型对象调用同一方法可能产生不同的行为(在重写了基类方法的前提下)

这就是继承的威力,至于为什么会产生这样的结果,原理是什么,我会在下一篇关于多态的文章中详细介绍。
尽管继承的威力十足,但是我们要慎用,一个最好的判断方法就是问一问自己是否要从新类向基类进行向上转型,如果有,那么就考虑使用继承,如果没有必要,则使用组合。

参考资料:《think in java》

猜你喜欢

转载自blog.csdn.net/qq_19894073/article/details/80835066