每个用JAVA的人都知道java不支持多继承,但为什么呢?无论从抽象还是多态等层面思考,感觉都是行得通的,那么为什么不支持呢?
很多人都是分析一旦一个类继承了多个父类,那么父类中如果有相同的成员变量和方法,就不好处理,如下图,这就是Diamond问题
GrandParent f()
/ / Parent1 f() Parent2 f()
/ / Son f()
那么此时子类如果我们只引用 f(),编译器将无法决定它应该调用哪个 f()方法,但此说明不足以让人信服,比如可以强制要求子类必须覆写f()方法。
Java之父,James Gosling在1995年的一份白皮书中给出了关于为什么不支持多继承
“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.”
主要就是说,Gosling认为,多继承是一种很少使用,并且很容易混淆的特性,所以Java语言就像删除操作符重载特性一样删除了多继承这种特性。
也就是说java为了便于程序员理解和使用,去除了一些不容易理解的特性,例如类的多继承。并非不能实现。
那为什么接口可以呢?
针对于Diamond(钻石)问题,接口由于本身都是抽象方法,继承谁都无所谓,都是需要其实现类去实现的,故不存在此问题。
此时有人问了,jdk1.8以后,java接口被赋予了一个新的功能,可以通过default关键字定义非抽象方法,那如果出现一个接口继承的父接口有相同的非抽象方法怎么办呢?
下面我们看看jdk1.8中如何处理
public interface Aservice {
void say();
default void bye(){
System.out.println("a service say bye");
}}public interface Bservice {
void say();
default void bye(){
System.out.println("b service say bye");
}}
此时我们定义接口去继承,如下图,发现被强制要求覆写相同的非抽象方法,以保证编译器知道具体执行哪个方法。
因此接口是可以的多继承的,即使jdk1.8中添加了非抽象方法。