8: Interfaces & Inner Classes(接口與內部類)

接口(interface)
當你implements一個interface的時候,你必須把這個interface的方法定義成public的。如果你不這么做,那它就會變成package權限的,這樣經過繼承,這些方法的訪問權限就會受到限制,而這是Java的編譯器所不允許的。
Java的“多重繼承”
interface既給了你abstract類的好處,又給了你interface的好處,因此只要基類的設計里面可以不包括婦女干法和成員變量的定義,你就應該優先使用interface。
合并接口時的名字沖突
在合并的接口里面放上同名方法,通常也會破壞程序的可讀性。
用繼承擴展interface
通常情況下,extends只能用于類,但是由于一個interface可以由多個接口拼接而成,因此創建新的interface的時候可以用extends來表示其多個“基接口(base interfaces)”。interface的名字要由逗號分隔。
常量的分組
interface是一種非常方便的,創建一組常量值的工具。
這種方法通常被稱為使用“神奇數字”,并且使得代碼的維護變得非常困難。
初始化接口中的數據成員
這些數據都不算是接口的組成部分,相反它們保存在這個接口的靜態存儲區內。
接口的嵌套
實現private接口就成了一種“強制你區定義那個接口的方法,但是又不讓你添加任何類型信息(也就是說不允許上傳)”的手段了。
接口與接口也可以嵌套,不過接口的規則仍然有效——特別是接口的所有元素都必須是public的這條,因此嵌套在接口中的接口也都自動是public的,它們不能是private的。
特別要注意的是,實現接口的時候,不一定要實現嵌套在里面的接口。同樣private接口只能在定義它的類里實現。

內部類
內部類是一種非常有價值的特性,它能讓你在邏輯上將相互從屬的類組織起來,并且在類的內部控制訪問權限。但是切記,內部類和合成是截然不同的,這一點非常重要。
內部類與上傳
普通類(非內部類)是不能被定義成private或protected的;它們只可能是public或package權限的。
在方法和作用域里的內部類
內部類可以被創建在方法內部,甚至是任何一個作用領域。這么做有兩個理由:
1. 就像前面所說的,你在實現某個接口,這樣你才能創建并且返回這個接口的reference。
2. 你正在處理一個復雜的問題,需要創建一個類,但是又不想讓大家都知道還有這么一個類。
匿名內部類
如果你在定義匿名內部類的時候,還要用到外面的對象,那編譯就會要求你把這個參數的reference聲明成final的。如果你忘了,編譯的時候就會報錯。
實際上實例初始化過程就是匿名內部類的構造函數。當然,它的功能是有限的;你不能重載實例初始化,因此你只能有一個構造函數。
與宿主類的關系
嵌套類

如果你不需要這種“內部類對象和宿主類對象之間”的聯系,那么你可以把內部類定義成static的。潛逃類的意思是:
1. 無須宿主類的對象就能創建嵌套類的對象。
2. 不能在嵌套類的對象里面訪問非static的宿主類對象。
普通內部類的成員數據和方法只能到類的外圍這一層,因此普通的內部類里不能有static數據,static數據成員或嵌套類。但是,這些東西嵌套類里都可以有。
普通(非static)的內部類需要使用特殊的this reference來與宿主類對象保持聯系。而嵌套類不需要這個this reference,這就使得它與static方法有些相似了。
引用宿主類的對象
在多層嵌套的類里向外訪問
繼承內部類

等到要創建構造函數的時候,默認的構造函數玩不轉了,你必須傳給他宿主類對象的reference。此外,你還必須在構造函數里面使用這種語法:
enclosingClassReference.super();
這樣才能提供那個必須的reference,而程序也才能編譯通過。
內部類可以被覆寫嗎?
本地內部類(Local inner classes)
選擇本地內部類而不是匿名內部類的唯一原因就是,你必須創建那種類的對象。
內部類的標識符(Inner class identifiers)

為什么要有內部類?
每個內部類都可以獨立地繼承某個“實現(implementation)”。因此,內部類不會受“宿主類是否已經繼承了別的實現”的約束。
1. 內部類可以有多個實例,而每個又都可以有它自己的,與宿主類對象無關的狀態信息。
2. 一個宿主類里可以放上好幾個內部類,它們可以用各自不同的方式來實現同一個interface或繼承同一個類。
3. 內部類對象創建的時機與宿主類對象的創建沒什么關系。
4. 內部類不存在什么讓人頭暈的“是”關系;他是一個獨立的實體。
Closure與回調(Closures & Callbacks)
創建內部類的時候,別去擴展或者修改宿主類的接口。
內部類與控制框架(Inner classes & control frameworks)
1. 在一個類里完整地實現整個控制框架,這樣就把“實現”里的所有獨一無二東西全部都給封裝起來了。內部類則用來表示各種解決具體問題所需的action()。
2. 內部類可以讓這個實現看上去不至于太古怪,因為它還可以直接訪問宿主類的所有成員。要不是這樣的話,代碼就會變得非常雜亂,這樣到最后你肯定會去找一個替代方案的。

總結

練習