熟悉 Java 的小伙伴应该知道 Java 有个很重要的特性就是它不支持多重继承。但是使用过其他面向对象编程语言的童鞋会知道,有的语言是支持多重继承的,比如 C++,Python.
我们来看看 ”Java 之父“:James Gosling 老爷子说过的这样一句话。
JAVA omits many rarely used, poorly understood, confusing features of C++ that in our experience bring more grief than benefit. This primarily consists of operator overloading (although it does have method overloading), multiple inheritance, and extensive automatic coercions.
简单的翻译一下:Java 去除了一些 C++ 中很少用、而且被经常误解而错用的功能,如操作符的重载(尽管 Java 仍旧保留方法的重载),多重继承,以及广泛的自动强迫同型(extensive automatic coercions)。
那么多重继承为什么会被错用呢?或者说是多重继承容易出现什么问题?我们来看一下下面这个比较著名的 “ 多重继承的钻石问题 ”
我们假设类 A、B、C 内的方法都是 public 的,以方便讨论。
类 B 和类 C 继承自类 A,且都重写了类 A 中的同一个方法,而类 D 同时继承了类 B 和类 C,那么此时类 D 会继承 B、C 的方法,那对于 B、C 重写的 A 中的方法,类 D 会继承哪一个呢?
看到这里,相信大家也明白了多重继承会导致这种有歧义的情况存在。
在 C++ 和 Python 中又称这种情况为二义性,对此 C++ 的解决办法是在调用前指定类名,或者使用同名覆盖。而 Python 也是需要指明需要使用的是哪个父类的方法。并且其实,这两种语言在支持多重继承这个角度上也都建议要把这种多个父类中的出现同名方法的情况给尽量避免掉。
所以考虑到这种二义性问题,Java 不支持多重继承。
但是 Java 支持多接口实现,现在,我们想一想,多接口实现为何就不会存在二义性问题?
很简单,因为接口中的方法,是抽象的(从JDK1.8之后,接口中允许给出一些默认方法的实现,这里不考虑这个),就算一个类实现了多个接口,且这些接口中存在某个同名方法,但是我们要清楚的知道,这个同名方法最终需要由这个类自己来实现,所以并不会出现二义性的问题。
但是有的小朋友就会问了,不同接口中定义了相同的方法不会造成二义性的问题,但是接口允许定义 public static 的变量啊,那如果变量名一样,不也是会有二义性问题吗?
我们来自己验证一下这个问题,定义两个接口,两个接口中都声明一个叫做 num 的整型变量。
package InnerClass;
public interface Inter1 {
public static final int num = 1;
}
package InnerClass;
public interface Inter2 {
public static final int num = 2;
}
后声明一个测试类 test 去实现这两个接口,且在该测试类的 main 方法中,访问这个 num。
package InnerClass;
public class Test implements Inter1,Inter2{
public static void main(String[] args) {
System.out.println(num);
}
}
我们执行一下编译。
编译都无法通过。。。所以说 Java 的多接口实现避免了二义性问题。而如果你就想要多重继承,多接口实现满足不了你的话,那么你可以采用内部类的方式来设计你的程序,它在一定程度上弥补了 Java 的不支持多继承的缺陷(这是我在看《Thinking in Java》这本书中讲内部类时作者说的,当然我到现在也想不明白,什么场景下就非得用多重继承,多接口实现就不行?)
————————————————
原文链接:https://blog.csdn.net/u013568373/java/article/details/93317194