先來看看多繼承會帶來的問題,繼承容易致使鑽石危機(也稱棱形問題),一幅圖來講說明:java
假設 類A 中有一個public方法 fun(),而後 類B 和 類C 同時繼承了 類A,在 類B 或 類C 中各自對方法 fun()進行了覆蓋,這時 類D 經過多繼承同時繼承了 類B 和 類C,這樣便致使鑽石危機了,程序在運行的時候對於方法 fun()該如何判斷?ui
總結以下,主要有兩個方面:spa
(1)若是在一個子類繼承的多個父類中擁有相同名字的實例變量,子類在引用該變量時將產生歧義,沒法判斷應該使用哪一個父類的變量。 (2)若是在一個子類繼承的多個父類中擁有相同方法,子類中有沒有覆蓋該方法,那麼調用該方法時將產生歧義,沒法判斷應該調用哪一個父類的方法。 在接口中不能有實例變量,只能有靜態的常量,不能有具體的方法(包含方法體),只能有抽象方法,所以也就摒棄了多繼承的缺點。 對於一個類實現多個接口的狀況,由於接口只有抽象方法,具體方法只能由實現接口的類實現,在調用的時候始終只會調用實現類的方法(不存在歧義),所以不存在 多繼承的第二個缺點;而又由於接口只有靜態的常量,可是因爲靜態變量是在編譯期決定調用關係的,即便存在必定的衝突也會在編譯時提示出錯;而引用靜態變量通常直接使用類名或接口名,從而避免產生歧義,所以也不存在多繼承的第一個缺點。 對於一個接口繼承多個父接口的狀況也同樣不存在這些缺點。
可是java中能夠用接口和內部類的方式來間接達到多繼承的效果:code
//這是經過接口來間接實現多繼承的繼承
interface HowEat{接口
public abstract String howeat();ci
}it
class Chenken implements HowEat{編譯
public String howeat(){class
return "chicken: fry it ";
}
}
class Orange implements HowEat{
public String howeat(){
return "orangr: make it juice";
}
}
//這是經過內部類來實現的
class Father{
public void output(){
System.out.println("father");
}
}
class Mother{
public void output(){
System.out.println("mather");
}
}
class son{
class Father_son extends Father{
}
class Mother_son extends Mother{
}
public void father(){
(new Father_son()).output();
}
public void mather(){
(new Mother_son()).output();
}
}