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

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

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

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

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

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

總結(jié)

練習(xí)