java 多继承

多继承平时用得不多,所以从来没有系统性地总结过。最近又知道了一种实现多重继承的新方法,所以稍微研究一下。

这里要强调一点,java从来不允许“实现多继承”,这种说法是错误的。java只允许“声明多继承”,从而达到多继承的效果。

参考:https://www.zhihu.com/question/24317891/answer/65097560

 

一、什么是多继承

多继承指的是一个类可以同时从多于一个的父类那里继承行为和特征。举个例子,男人既是人类也是动物,不仅有人类的智慧,也有动物的野性。

Java只允许单继承。在大多数情况下,我认为没有必要使用多继承。如果确实出现了这种设计,那就要思考一下设计是否存在问题了。

但是,多继承在某些特殊的设计下是有使用场景的。

举个例子:孩子继承了父亲的行为和特征,同时也继承了母亲的行为和特征,这时候子类需要同时继承两个父类。但是刚才提到了,Java只允许单继承,怎么办?

为了解决这类问题,Java从侧面提供了两种间接方法声明多继承,一种方法需要使用接口,另一种方法需要使用内部类。

二、为什么Java只允许单继承

总是提到Java只允许单继承,这是为什么呢?

原因是多继承容易引发语义不明确。举个例子:

如果允许多继承,那么假设存在一个类Xie,Xie既会写Java又会写Go,所以Xie可以继承父类Javaer和父类Goer,从而获取父类中的方法write。

现在问题来了,Javer中存在一个方法为write,Goer中也存在一个方法为write,子类Xie在调用父类的write方法时,是调用Javaer的write呢?还是调用Goer的write呢?

Java无法处理这种情况,只好干脆地禁止多继承。

 

三、声明多继承

再次强调一点,java从来不允许“实现多继承”,这种说法是错误的。java只允许“声明多继承”,从而达到多继承的效果。

(1)继承单个类的同时实现接口

可以通过继承单个类的同时实现接口的方式声明多重继承。

在这里,child类继承了父类Father的strong方法,同时也实现了接口Mother的clever方法,从而同时拥有了不同类的特性。

这就是我认为“Java实现多重继承”的说法不正确的原因。这种方法明显没有使用两次extend,只是在继承父类的同时,实现了接口,仅此而已。应该称之为“声明多继承”。

在这里要注意接口中可以声明default方法,实现类可以继承接口中的default方法,从而实现多继承。详情见:

http://www.xie4ever.com/2017/06/03/java-java8%e4%b8%ad%e7%9a%84default%e6%96%b9%e6%b3%95/

(2)内部类

接口方式只限于单独的一个父类和多个接口的情况。如果一个类想要继承来自多个类的特性,就必须使用内部类的形式。

这种方式强行在子类的内部实现了父类(内部类),从而使子类拥有了父类的特性,类似于继承了父类。

(3)Java 8中的改变

从Java 8开始,接口允许为方法提供“默认实现”了——默认方法(default method)。

因而实质上Java 8的接口多继承其实也会涉及到实现多继承,并且语言层面有专门规定去解决实现多继承时选择哪个版本的问题——哪个都不选择,而是在发现会继承多个默认方法实现并且没有override时报错,逼使用户显式override可能冲突的方法。

这使得Java 8开始接口可以当作c++中的traits来使用,达到实现多继承的目的。

实现的关键在default关键字上,下次另开文章分析这个关键字。

四、总结

“多继承”设计时就比较复杂,再加上实现方法比较曲折,平时又用得很少,所以不好理解。实际编码应该尽量避免使用多继承。

发表评论

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