8: Interfaces & Inner Classes(接口與內(nèi)部類(lèi))
接口(interface)
當(dāng)你implements一個(gè)interface的時(shí)候,你必須把這個(gè)interface的方法定義成public的。如果你不這么做,那它就會(huì)變成package權(quán)限的,這樣經(jīng)過(guò)繼承,這些方法的訪(fǎng)問(wèn)權(quán)限就會(huì)受到限制,而這是Java的編譯器所不允許的。
Java的“多重繼承”
interface既給了你abstract類(lèi)的好處,又給了你interface的好處,因此只要基類(lèi)的設(shè)計(jì)里面可以不包括婦女干法和成員變量的定義,你就應(yīng)該優(yōu)先使用interface。
合并接口時(shí)的名字沖突
在合并的接口里面放上同名方法,通常也會(huì)破壞程序的可讀性。
用繼承擴(kuò)展interface
通常情況下,extends只能用于類(lèi),但是由于一個(gè)interface可以由多個(gè)接口拼接而成,因此創(chuàng)建新的interface的時(shí)候可以用extends來(lái)表示其多個(gè)“基接口(base interfaces)”。interface的名字要由逗號(hào)分隔。
常量的分組
interface是一種非常方便的,創(chuàng)建一組常量值的工具。
這種方法通常被稱(chēng)為使用“神奇數(shù)字”,并且使得代碼的維護(hù)變得非常困難。
初始化接口中的數(shù)據(jù)成員
這些數(shù)據(jù)都不算是接口的組成部分,相反它們保存在這個(gè)接口的靜態(tài)存儲(chǔ)區(qū)內(nèi)。
接口的嵌套
實(shí)現(xiàn)private接口就成了一種“強(qiáng)制你區(qū)定義那個(gè)接口的方法,但是又不讓你添加任何類(lèi)型信息(也就是說(shuō)不允許上傳)”的手段了。
接口與接口也可以嵌套,不過(guò)接口的規(guī)則仍然有效——特別是接口的所有元素都必須是public的這條,因此嵌套在接口中的接口也都自動(dòng)是public的,它們不能是private的。
特別要注意的是,實(shí)現(xiàn)接口的時(shí)候,不一定要實(shí)現(xiàn)嵌套在里面的接口。同樣private接口只能在定義它的類(lèi)里實(shí)現(xiàn)。
內(nèi)部類(lèi)
內(nèi)部類(lèi)是一種非常有價(jià)值的特性,它能讓你在邏輯上將相互從屬的類(lèi)組織起來(lái),并且在類(lèi)的內(nèi)部控制訪(fǎng)問(wèn)權(quán)限。但是切記,內(nèi)部類(lèi)和合成是截然不同的,這一點(diǎn)非常重要。
內(nèi)部類(lèi)與上傳
普通類(lèi)(非內(nèi)部類(lèi))是不能被定義成private或protected的;它們只可能是public或package權(quán)限的。
在方法和作用域里的內(nèi)部類(lèi)
內(nèi)部類(lèi)可以被創(chuàng)建在方法內(nèi)部,甚至是任何一個(gè)作用領(lǐng)域。這么做有兩個(gè)理由:
1. 就像前面所說(shuō)的,你在實(shí)現(xiàn)某個(gè)接口,這樣你才能創(chuàng)建并且返回這個(gè)接口的reference。
2. 你正在處理一個(gè)復(fù)雜的問(wèn)題,需要?jiǎng)?chuàng)建一個(gè)類(lèi),但是又不想讓大家都知道還有這么一個(gè)類(lèi)。
匿名內(nèi)部類(lèi)
如果你在定義匿名內(nèi)部類(lèi)的時(shí)候,還要用到外面的對(duì)象,那編譯就會(huì)要求你把這個(gè)參數(shù)的reference聲明成final的。如果你忘了,編譯的時(shí)候就會(huì)報(bào)錯(cuò)。
實(shí)際上實(shí)例初始化過(guò)程就是匿名內(nèi)部類(lèi)的構(gòu)造函數(shù)。當(dāng)然,它的功能是有限的;你不能重載實(shí)例初始化,因此你只能有一個(gè)構(gòu)造函數(shù)。
與宿主類(lèi)的關(guān)系
嵌套類(lèi)
如果你不需要這種“內(nèi)部類(lèi)對(duì)象和宿主類(lèi)對(duì)象之間”的聯(lián)系,那么你可以把內(nèi)部類(lèi)定義成static的。潛逃類(lèi)的意思是:
1. 無(wú)須宿主類(lèi)的對(duì)象就能創(chuàng)建嵌套類(lèi)的對(duì)象。
2. 不能在嵌套類(lèi)的對(duì)象里面訪(fǎng)問(wèn)非static的宿主類(lèi)對(duì)象。
普通內(nèi)部類(lèi)的成員數(shù)據(jù)和方法只能到類(lèi)的外圍這一層,因此普通的內(nèi)部類(lèi)里不能有static數(shù)據(jù),static數(shù)據(jù)成員或嵌套類(lèi)。但是,這些東西嵌套類(lèi)里都可以有。
普通(非static)的內(nèi)部類(lèi)需要使用特殊的this reference來(lái)與宿主類(lèi)對(duì)象保持聯(lián)系。而嵌套類(lèi)不需要這個(gè)this reference,這就使得它與static方法有些相似了。
引用宿主類(lèi)的對(duì)象
在多層嵌套的類(lèi)里向外訪(fǎng)問(wèn)
繼承內(nèi)部類(lèi)
等到要?jiǎng)?chuàng)建構(gòu)造函數(shù)的時(shí)候,默認(rèn)的構(gòu)造函數(shù)玩不轉(zhuǎn)了,你必須傳給他宿主類(lèi)對(duì)象的reference。此外,你還必須在構(gòu)造函數(shù)里面使用這種語(yǔ)法:
enclosingClassReference.super();
這樣才能提供那個(gè)必須的reference,而程序也才能編譯通過(guò)。
內(nèi)部類(lèi)可以被覆寫(xiě)嗎?
本地內(nèi)部類(lèi)(Local inner classes)
選擇本地內(nèi)部類(lèi)而不是匿名內(nèi)部類(lèi)的唯一原因就是,你必須創(chuàng)建那種類(lèi)的對(duì)象。
內(nèi)部類(lèi)的標(biāo)識(shí)符(Inner class identifiers)
為什么要有內(nèi)部類(lèi)?
每個(gè)內(nèi)部類(lèi)都可以獨(dú)立地繼承某個(gè)“實(shí)現(xiàn)(implementation)”。因此,內(nèi)部類(lèi)不會(huì)受“宿主類(lèi)是否已經(jīng)繼承了別的實(shí)現(xiàn)”的約束。
1. 內(nèi)部類(lèi)可以有多個(gè)實(shí)例,而每個(gè)又都可以有它自己的,與宿主類(lèi)對(duì)象無(wú)關(guān)的狀態(tài)信息。
2. 一個(gè)宿主類(lèi)里可以放上好幾個(gè)內(nèi)部類(lèi),它們可以用各自不同的方式來(lái)實(shí)現(xiàn)同一個(gè)interface或繼承同一個(gè)類(lèi)。
3. 內(nèi)部類(lèi)對(duì)象創(chuàng)建的時(shí)機(jī)與宿主類(lèi)對(duì)象的創(chuàng)建沒(méi)什么關(guān)系。
4. 內(nèi)部類(lèi)不存在什么讓人頭暈的“是”關(guān)系;他是一個(gè)獨(dú)立的實(shí)體。
Closure與回調(diào)(Closures & Callbacks)
創(chuàng)建內(nèi)部類(lèi)的時(shí)候,別去擴(kuò)展或者修改宿主類(lèi)的接口。
內(nèi)部類(lèi)與控制框架(Inner classes & control frameworks)
1. 在一個(gè)類(lèi)里完整地實(shí)現(xiàn)整個(gè)控制框架,這樣就把“實(shí)現(xiàn)”里的所有獨(dú)一無(wú)二東西全部都給封裝起來(lái)了。內(nèi)部類(lèi)則用來(lái)表示各種解決具體問(wèn)題所需的action()。
2. 內(nèi)部類(lèi)可以讓這個(gè)實(shí)現(xiàn)看上去不至于太古怪,因?yàn)樗€可以直接訪(fǎng)問(wèn)宿主類(lèi)的所有成員。要不是這樣的話(huà),代碼就會(huì)變得非常雜亂,這樣到最后你肯定會(huì)去找一個(gè)替代方案的。
總結(jié)
練習(xí)
「讀書(shū)筆記」Thinking in Java 3rd Edition - 8: Interfaces & Inner Classes
只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。 | ||
![]() |
||
網(wǎng)站導(dǎo)航:
博客園
IT新聞
Chat2DB
C++博客
博問(wèn)
管理
|
||
相關(guān)文章:
|
||