四。類和接口
第12條:使類和成員的可訪問能力最小
為了更好的實現信息隱藏,降低各模塊的耦合度,盡可能地降低類和成員的訪問能力是必須的。有一點特別關鍵,就是公有的靜態final域幾乎全部是錯誤的。客戶可以修改這樣的成員數組,應該改為私有的才是安全的。
第13條:支持非可變類
使一個類成為非可變類需要做到以下5點:
1。不能提供任何會修改對象的方法
2。保證沒有可被子類覆寫的方法,可以通過使這個類為final來達到
3。使所有的成員變量都是final
4。使所有的成員變量都為私有
5。保證對於任何可變組件互斥訪問
使一個類成為非可變類的的優點:
1。非可變類通常比較簡單,呵呵,這點很明顯,他只有一個狀態
2。非可變類通常是線程安全的
3。非可變類為其他對象提供了很多構件
4。非可變類最大的缺點在於對於每個不同的值(或者說狀態),都要求一個單獨的對象,在某些情況下你需要創建非常多的對象,性能上有很大影響
盡管如此,盡力使每一個類成為非可變類應該是你追求的目標。
第14條:復合優於繼承
昨天在看《面向對象編程導論》,提到“子類”和“子類型”是不同的,替換原則只適合於子類型關系,而一般編程語言只是考慮了子類關系,子類說明了新類是繼承自父類,而子類型強調的是新類具有父類一樣的行為(未必是繼承)。那麼,什麼時候才應該使用繼承?那就是符合子類型關系的時候,或者一般所說的”is a"關系,你必須保證新類的行為與父類完全一致!!!在任何使用父類的場合,新類應該表現一樣的行為。
繼承是OOP最重要的概念之一,但是繼承也破壞了“封裝性”,子類的實現要依賴於父類的實現細節。所以,除了上面提到的情況外,你應該盡量用復合取代繼承。(在覆寫equals()方法也提到了這點)否則都屬於繼承的濫用,技術的濫用已經屢見不鮮了。
第15條:要麼專門的設計,以使用繼承,並給出文檔說明,要麼禁止繼承
這點跟上面一點強調的一樣。如果你要使用繼承,請做好設計,在構造函數,clone(),readSolve()方法中不要調用任何可變的方法,並寫出詳細的文檔說明。其實最好的情況,還是不使用的好!
第16條:接口優於抽象類
接口是定義具有多個實現的類型的最佳途徑,這點很明顯,每個具體類實現接口不同。如果當演化的容易性比靈活性更重要的時候,你應該使用抽象類。如,你要往抽象類中增加一個方法,任何實現這個抽象類的子類就自動具有這一個方法,而接口則不能,所有公有的接口的設計要非常謹慎,並保證盡力對外不做修改。在使用接口的時候,一般都設計一個抽象類作為“骨架”,這個抽象類應該盡可能地小,只保留有最基本的功能。
第17條:接口只是被用於實現類型
你實現了一個接口,就代表這個類是該接口的類型。在應用我們經常看到在接口中定義靜態公有的常量,這其實是對接口的誤用(汗,我是這種錯誤的典型),如
public interface Constants{
public int ONE=1;
......
}這樣的形式完全是錯誤的,應該使用一個不能產生實例的類來代替
public class Constants{
private COnstants(){} //構造函數為私有
pulic static final int ONE=1;
......
}
第18條:應該優先考慮靜態內部類
非靜態類總是和外部類的實例相聯系,應該盡量使用靜態內部類。