控制對成員的存取權限有兩個原因:
第一是為了使使用者不要碰觸那些他們不該碰觸的部分,這些部分對於類內部的操作是必要的,但是它井不屬於用戶端程式員所需介面的一部分。因此,將方法和域指定成private,對用戶端程式員而言是一種服務。因為這樣他們可以很清楚地看到什麼對他們重要,什麼是他們可以忽略的。這樣簡化了他們對類的理解。
第二個原因,也是最重要的原因,是為了讓類庫設計者可以更改類的內部工作方式,而不必擔心這樣會對用戶端程式員產生重大的影響。例如,最初可能會以某種方式建立一個類,然後發現如果更改程式結構,可以大大提高運行速度。
如果介面和實現可以被明確地隔離和加以保護,那麼就可以實現這一目的,而不必強制用戶端程式員重新編寫代碼。存取權限控制可以確保不會有任何用戶端程式員依賴於某個類的底層實現的任何部分。
當具備了改變底層實施細節的能力時,不僅可以隨意地改善設計,還可能會隨意地犯錯誤,同時也就有了犯錯的可能性。無論如何細心地計劃並設計,都有可能犯錯。當瞭解到您所犯錯誤是相對安全的時候,就可以更加放心地進行實驗,也就可以更快地學會,更快地完成項目。
類的公用介面是使用者真正能夠看到的,所以這一部分是在分析和設計的過程中決定該類是否正確的最重要的部分。儘管如此,您仍然有進行改變的空間。如果在最初無法建立出正確的介面,那麼只要不刪除任何用戶端程式員在他們的程式中已經用到的東西,就可以在以後添加更多的方法。
final資料
對於基本類型,final使資料恒定不變;而對於對象引用,final使引用恒定不變。一旦引用被初始化指向一個對象,就無法再把它改為指向另一個對象。然而,對象其自身卻使可以改變的,Java並未提供使任何對象恒定不變的途徑。這一限制同樣適用與數組,它也是對象。
final方法
“覆蓋”只有在某方法是基類的介面的一部分時才會出現。即,必須能將一個對象向上轉型為它的基本類型並調用相同的方法。如果某方法為private,它就不是基類的介面的一部分。它僅是一些隱藏於類中的代碼,只不過是具有相同的名稱而已。但如果在匯出類以相同的方法產生一個public、protected或包存取權限方法的話,該方法就不會產生在基類中出現的 “僅具有相同名稱”的情況。此時,你並沒有覆蓋該方法,僅是產生了一個新的方法。由於
private方法無法觸及而且能有效隱藏,所以除了把它看成是因為它所歸屬的類的組織圖的原因而存在外,其他任何事物都不需要考慮它。
繼承和組合
繼承和組合都能從現有類型產生新類型。組合一般是將現有類型作為新類型底層實現的一部分來加以複用,而繼承複用的是介面。由於匯出類具有基類介面,所以它可以向上轉型至基類,這對多態來講至關重要。
儘管物件導向編程對繼承極為強調,但在開始一個設計時,一般應優先選擇使用組合,只有在確實必要時才使用繼承。因為組合更具靈活性。此外,通過對成員元類型使用繼承技術(這裡不理解。我覺得是組合技術。求解!)的添加技巧,可以在運行時改變那些成員對象的類型和行為。因此,可以在運行時改變組合而成的對象的行為。
在設計一個系統時,目標應該是找到或建立某些類,其中每個類都有具體的用途,而且既不會太大(包含太多的功能而難以複用),也不會太小(不添加其他功能就無法使用)。
多態中“覆蓋”私人方法(參看final方法)
public class PrivateOverride{ private void f(){ System.out.println("private f()"); } public static void main(String a[]){ PrivateOverride po = new Derived(); po.f(); }}class Derived extends PrivateOverride{ public void f(){ System.out.println("public f()"); }}
我們所期望的輸出是“public f( )”(輸出卻是"private f()”),但是由於private方法被自動認為就是final方法,而且對匯出類是屏蔽的。因此,在這種情況下,Derived類中的f( ) 方法就是一個全新的方法;既然基類中f( ) 方法在子類Derived中不可見,因此也就沒有被重載。
結論就是:只有非private方法才可以被重載;但是我們還需要密切注意重載private方法的現象,雖然編譯不會出錯,但是不會按照我們所期望的來執行。明白地說,在匯出類中,對於基類中的private方法,我們最好用一個不同的名字。、
以上內容整理自《java編程思想》