每個用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(&34;); }}public interface Bservice { void say(); default void bye(){ System.out.println(&34;); }}
此時我們定義接口去繼承,如下圖,發現被強制要求覆寫相同的非抽象方法,以保證編譯器知道具體執行哪個方法。
因此接口是可以的多繼承的,即使jdk1.8中添加了非抽象方法。