這裡的繼承是實現繼承而非介面繼承。
與方法呼叫不同的是,繼承打破了封裝性:
換句話說,子類依賴於其超類中特定功能的實現細節。超類的實現有可能會隨著髮型版本的不同而發生改變,如果真的發生了變化,子類可能會遭到破壞,即使他的**完全沒有改變。因此,子類必須跟著超類的更新而改變,除非超類是專門為擴充套件而設計的,並用具有很好的文件說明。
只有當子類真正是超類的子型別(subtype)時,才適合用繼承,也就是是「is-a」關係時。
如果在適合於是用復合的地方是用了繼承,則會不必要的暴漏實現細節。這樣的到的api會把你限制在原始的實現上,永遠限定了類的效能。更為嚴重的是,由於暴漏了內部細節,客戶端就有可能直接訪問這些內部細節。這樣至少會導致語義上的混淆。例如:properties,getproperty(string key)就有可能產生與get(object key) 不同的結果。
對於你正檢視擴充套件的類,他的api有沒有缺陷?如果有,你願意把那些缺陷傳播到子類的api中?而符合則允許設計新的api來隱藏這些缺陷。
可以不擴充套件現有的類,而是在新類中增加乙個私有域,他 引用現有類乙個例項。這種設計叫做「復合(composition)」,因為現有的類變成新類的乙個元件。新類中的每個例項方法都可以呼叫被包含的現有類例項中對應的方法,並返回他的結果。這被成為**(forwarding),新類中的方法被成為**方法(forwarding method)。
第四章 類和介面 第16條 復合優先於繼承
本條目討論的問題並不適用於介面繼承 與方法呼叫不同的是,繼承打破了封裝性,如果超類中特定功能的實現細節發生了變化,子類可能會遭到破壞,即使它的 完全沒有改變,除非超類是專門為了擴充套件而設計的,並且有很好文件說明 例項 public class instrumentedhashsetextends ...
Java程式設計之 復合優先於繼承
組合 通過建立乙個由其他物件組合的物件來獲得新功能的重用方法 新功能的獲得是通過呼叫組合物件的功能實現的 有時又叫聚合 例如 乙個物件擁有或者對另外乙個物件負責並且兩個物件有相同的生命週期。gof 乙個物件包含另乙個物件集合 被包含物件對其他物件是不可見的並且只能從包含它的物件中訪問的特殊組合形式 ...
第25條 列表優先於陣列
陣列與泛型相比,有兩個重要的不同點。陣列是協變的 如果sub是super的子型別,那麼陣列型別sub是super的子型別 相反,泛型是不可變得,對於任意兩個不同的型別t1和t2,list和list沒有子型別或超型別的關係。這段 在執行時出錯 object o new long 1 o 0 i don...