Java 8 的默認方法和多重繼承
Java 8 的默認方法和多重繼承
介紹
我一看到 Java 8 發布了, 就決定開始深入看看對于這門編程語言新的增強功能. 我承認,自己并沒有像對待 7 那樣對這個版本進行跟進, 所以我所知道的唯一的增強功能只是lambda表達式而已. 在我通讀文檔,并寫下一些示例程序來確保自己對這些新的特性有一個良好的理解是,有一個特性引起了我特別的注意: 默認方法,首先,讓我們來看一看它們到底是什么.
先認識認識
從本質上講,默認方法就是一個在接口里面有了一個實現的方法. 傳統的接口只是簡單的由抽象方法和公共靜態的并且是final的變量構成. 那么考慮看看下面這個:
public interface ExampleInterface { public void exampleMethod(); default public void exampleDefaultMethod() { // Some implementation code here } }
如果一個類決定去實現 ExampleInterface, 它只需要去實現 exampleMethod, 并且它可以簡單地采用 exampleDefaultMethod的默認實現. 現在,讓我們來看看Oracle打算讓我們怎樣去使用它們.
它們應該怎么被使用
這個想法不是讓你在設計時考慮使用默認方法作為解決方案,而是它們只是一個事后的考慮. 在Oracle的跟蹤報道上他們稱述的意圖是去“確保為那些老版本接口寫的代碼的二進制兼容性”(1). 從本質上講,你和你的開發人員編寫了對某些接口的多個實現,但是你想要添加新的一塊東西. 然而,這樣做就意味著對所有那些實現了這個接口的類進行重新構建都將失敗,除非你為它們每一個都補上新增的那一塊的實現. 默認方法的想法是你可以在不改變現有實現并且再也不用變更它們的前提下加入對接口的新需求.
但是讓我們退后一步想想. 這里面還是有些問題的吧. 首先,讓我們接受有時高級別 的變更(比如變更你的接口)行將發生的這一事實. 然而,讓我們也不要忘了接口的存在的目的是什么. 理想情況下一個接口鎖定一些高級別的對象,或者說你是在創造一些特殊功能部分的API. 如果一些類只需要去實現接口功能 的某些部分,而不是全部的話, 那么那會是一個好的設計嗎? 那不就是抽象類被設計出來的原因么?
其次,這會引入對于處理多重繼承的需求. 而現在謝天謝地,如果你有兩個擁有一個對于單個方法簽名的默認實現的接口, 而你嘗試去擁有一個同時實現這兩個接口的類, Java將拒絕編譯這個類. 許多人抱怨接口中允許公共靜態變量的不確定性,說如果兩個接口中有同一個變量就會有些模棱兩可(因此像 C# 這樣的編程語言就會禁止諸如此類的事情), 而這是有一些難以對付的.
我看到這個功能是如何在這個問題上起作用的, 而我不準備在這里闡述它,直到我看到它被應用在實踐中,但是我必須強調它使我感到緊張. 話雖這么說,讓我們還是來更多的看看這個功能可能會被運用到的地方,而不是它的這個目的.
可能的誤用
前面我們談到引入多重繼承后模棱兩可的問題, 那么編譯器不會捕捉到的會是什么情況呢? 什么才會使我停止像我使用一個抽象類(通常是一些抽象方法和一些實現)那樣,簡單的使用接口的做法,而去利用繼承多個接口的好處呢? 這沒有怎么不好,但是究其自身而言,它將會鼓勵使用Java努力避免的復雜設計. 有些情況是在你實際需要多繼承來解決你在構建一個抽象類的框架中使用單個繼承類型所不能解決的問題.
總結
總的來說,Java8還是提供了許多很酷的新東西的, 有些看起來同Java早期的基礎知識相悖. 不管是好是壞,時間會證明一切. 如果你有任何建議,請自由的分享他們. 此外,任何時候開始在你的項目中使用Java 8,請自由分享你的成功或恐怖故事. 可以通過ryan.kenney@coveros.com聯系我.
參考
1 – http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html