Java为什么不支持多继承

一个类,只有一个父类的情况,我们叫做单继承。而一个类,同时有多个父类的情况,叫做多继承。

前面我们提到过:"Java中支持一个类同时实现多个接口,但是不支持同时继承多个类。但是这个问题在Java 8之后也不绝对了。"那么,是不是又很很想知道,为什么Java中不支持同时继承多个类呢?

多继承

一个类,只有一个父类的情况,我们叫做单继承。而一个类,同时有多个父类的情况,叫做多继承。在Java中,一个类,只能通过extends关键字继承一个类,不允许多继承。但是,多继承在其他的面向对象语言中是有可能支持的。像C++就是支持多继承的,主要是因为编程的过程是对现实世界的一种抽象,而现实世界中,确实存在着需要多继承的情况。比如维基百科中关于多继承举了一个例子:例如,可以创造一个“哺乳类动物”类别,拥有进食、繁殖等的功能;然后定义一个子类型“猫”,它可以从父类继承上述功能。但是,"猫"还可以作为"宠物"的子类,拥有一些宠物独有的能力。所以,有些面向对象语言是支持多重继承的。但是,多年以来,多重继承一直都是一个敏感的话题,反对者指它增加了程序的复杂性与含糊性。

菱形继承问题

假设我们有类B和类C,它们都继承了相同的类A。另外我们还有类D,类D通过多重继承机制继承了类B和类C。

这时候,因为D同时继承了B和C,并且B和C又同时继承了A,那么,D中就会因为多重继承,继承到两份来自A中的属性和方法。这时候,在使用D的时候,如果想要调用一个定义在A中的方法时,就会出现歧义。因为这样的继承关系的形状类似于菱形,因此这个问题被形象地称为菱形继承问题。而C为了解决菱形继承问题,又引入了虚继承 。因为支持多继承,引入了菱形继承问题,又因为要解决菱形继承问题,引入了虚继承。而经过分析,人们发现我们其实真正想要使用多继承的情况并不多。所以,在 Java 中,不允许“实现多继承”,即一个类不允许继承多个父类。但是 Java 允许“声明多继承”,即一个类可以实现多个接口,一个接口也可以继承多个父接口。由于接口只允许有方法声明而不允许有方法实现(Java 8以前),这就避免了 C 中多继承的歧义问题。

但是,Java不支持多继承,在Java 8中支持了默认函数(default method )之后就不那么绝对了。虽然我们还是没办法使用extends同时继承多个类,但是因为有了默认函数,我们有可能通过implements从多个接口中继承到多个默认函数,那么,又如何解决这种情况带来的菱形继承问题呢?这个问题,我们在后面的部分单独介绍。

下一节:本文将介绍一种可以帮助我们复用的新的概念——组合,通过学习组合和继承的概念及区别,并从多方面帮大家分析在写代码时如何进行选择。