每個用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 bene?t. 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中添加了非抽象方法。