Java省略了許多很少用到,缺乏了解,混淆功能的C + +,在我們的經驗中帶來更多的悲傷大于收益 。
-----James Gosling
James Gosling 這個人大家應該很熟悉,就是最初設計Java 語言的的程序員,被稱為“Java之父”,現在也有50多歲了,前幾天還看過他的視頻,很平易近人的一個白頭老人,可能和在中國小鎮隨處可見的老人是一樣 的,完全看不出是那 SUN 的副總裁,也沒有中國商人特有的做秀和狡黠。
上面那段話是別人問到他關于 Java 為什么不能運算符重載(雖然它確實有方法重載),多重繼承,以及廣泛的自動強制轉換時回答的一段話。他老人家說多繼承會帶來更多的悲傷,這悲傷到底在什么地方納?以下是我自己的一點分析(如有不正,希望大神你出手):
多繼承的優點是顯而易見的,一個子類能有多個父類的屬性和方法,比如上面的那個希臘神話當中的半人馬先生,繼承了人和馬,上半身是人的軀干,包括手和頭,下半身則是馬身,也包括軀干和腿,既有速度又有思維和抓取東西的能力。
但是多繼承的缺點也是一點就破:
(1)如果一個子類繼承的多個父類中擁有相同名字的實例變量,子類在引用該變量時將產生歧義,無法判斷應該使用哪個父類的變量;
貼段代碼給看看:
public class ClassA { protected String a = "same" ; } public class ClassB { protected String a = "Unsame" ; } public class ClassC extends ClassA, ClassB { public void printOut() { System.out.println( super .a); //-----關鍵的一行------- } public static void main(String[] args) { ClassC classC = new ClassC(); classC.printOut(); } } |
(PS:上面這段代碼是不能編譯的,我是舉個例子而已)classC到底會打印same還是Unsame納?
(2)如果一個子類繼承的多個父類中擁有相同方法,子類中有沒有覆蓋該方法,那么調用該方法時將產生歧義,無法判斷應該調用哪個父類的方法;
貼段代碼看看:
class ClassA { public void printOut() { System.out.println( "same" ); } } class ClassB { public void printOut() { System.out.println( "Unsame" ); } } public class ClassC extends ClassA, ClassB { public static void main(String[] args) { ClassC classC = new ClassC(); classC.printOut(); //-----關鍵的一行----- } } |
(PS:上面這段代碼是不能編譯的,我是舉個例子而已)classC到底會調用上面哪個父類的printOur()方法
上面的這些都是致命的歧義,所以java中禁止一個類繼承多個父類;
但是那個白頭發的老人在很多年前就給 java提供了接口,并能通過接口的功能獲得多繼承的許多優點而又摒棄了類與類多繼承的缺點。
這到底是怎們做到的納?嗯,好了,我們也來詳細的分析一下:
java允許一個接口繼承多個父接口,也允許一個類實現多個接口,而這樣的多繼承有上面提到的缺點嗎?
因為有接口的抽象性,所以答案肯定是沒有;
1)在接口中不能有實例變量,只能有靜態的常量,每個靜態的常量在程序開始運行前都已經初始化成功,如果有重命名的出現,編譯器先生會及時的告訴你的;
2)接口中不能有具體的方法(包含方法體),只能有抽象方法,具體的方法只能由實現接口的類實現,在調用的時候也只會調用實現類的方法,這樣是不會存在歧義的;
那門開篇的那半人馬就可以這樣來寫了:
interface Humain { String arm = "2只能抓東西的胳膊"; void output(); } interface Horse { String leg = "4只能跑的腿"; void output(); } interface Half extends Humain, Horse { } public class HalfHorse implements Half { // 實現上面倆個接口里面的同名方法 // 這個類擁有兩個接口的靜態變量 public void output() { System.out.println("我是個有" + arm + "和" + leg + "的半人馬"); } public static void main(String[] args) { HalfHorse halfhorse = new HalfHorse(); halfhorse.output(); } } |
(PS:上面這段代碼是可以編譯通過的)
因為引入了接口,所以程序員有很大空間的想象力,這可能就是Java吸引許多人的魅力之一了。