深入理解java中的組合和繼承
深入理解Java中的組合和繼承
本文將介紹組合和繼承的概念及區別,並從多方面分析在寫程式碼時如何進行選擇。
物件導向的複用技術
前面提到複用,這裡就簡單介紹一下物件導向的複用技術。
複用性是物件導向技術帶來的很棒的潛在好處之一。如果運用的好的話可以幫助我們節省很多開發時間,提升開發效率。但是,如果被濫用那麼就可能產生很多難以維護的程式碼。
作為一門物件導向開發的語言,程式碼複用是Java引人注意的功能之一。Java程式碼的複用有繼承,組合以及代理三種具體的表現形式。本文將重點介紹繼承複用和組合複用。
繼承
繼承(Inheritance)是一種聯結類與類的層次模型。指的是一個類(稱為子類、子介面)繼承另外的一個類(稱為父類、父介面)的功能,並可以增加它自己的新功能的能力,繼承是類與類或者介面與介面之間最常見的關係;繼承是一種is-a
關係。(圖片來自網路,侵刪。)
組合
組合(Composition)體現的是整體與部分、擁有的關係,即has-a
的關係。
組合與繼承的區別和聯絡
在
繼承
結構中,父類的內部細節對於子類是可見的。所以我們通常也可以說通過繼承的程式碼複用是一種白盒式程式碼複用
。(如果基類的實現發生改變,那麼派生類的實現也將隨之改變。這樣就導致了子類行為的不可預知性;)
組合
是通過對現有的物件進行拼裝(組合)產生新的、更復雜的功能。因為在物件之間,各自的內部細節是不可見的,所以我們也說這種方式的程式碼複用是黑盒式程式碼複用
。(因為組合中一般都定義一個型別,所以在編譯期根本不知道具體會呼叫哪個實現類的方法)
繼承
,在寫程式碼的時候就要指名具體繼承哪個類,所以,在編譯期
就確定了關係。(從基類繼承來的實現是無法在執行期動態改變的,因此降低了應用的靈活性。)
組合
,在寫程式碼的時候可以採用面向介面程式設計。所以,類的組合關係一般在執行期
確定。
優缺點對比
組 合 關 系 | 繼 承 關 系 |
---|---|
優點:不破壞封裝,整體類與區域性類之間鬆耦合,彼此相對獨立 | 缺點:破壞封裝,子類與父類之間緊密耦合,子類依賴於父類的實現,子類缺乏獨立性 |
優點:具有較好的可擴充套件性 | 缺點:支援擴充套件,但是往往以增加系統結構的複雜度為代價 |
優點:支援動態組合。在執行時,整體物件可以選擇不同型別的區域性物件 | 缺點:不支援動態繼承。在執行時,子類無法選擇不同的父類 |
優點:整體類可以對區域性類進行包裝,封裝區域性類的介面,提供新的介面 | 缺點:子類不能改變父類的介面 |
缺點:整體類不能自動獲得和區域性類同樣的介面 | 優點:子類能自動繼承父類的介面 |
缺點:建立整體類的物件時,需要建立所有區域性類的物件 | 優點:建立子類的物件時,無須建立父類的物件 |
如何選擇
相信很多人都知道物件導向中有一個比較重要的原則『多用組合、少用繼承』或者說『組合優於繼承』。從前面的介紹已經優缺點對比中也可以看出,組合確實比繼承更加靈活,也更有助於程式碼維護。
所以,
建議在同樣可行的情況下,優先使用組合而不是繼承。
因為組合更安全,更簡單,更靈活,更高效。
注意,並不是說繼承就一點用都沒有了,前面說的是【在同樣可行的情況下】。有一些場景還是需要使用繼承的,或者是更適合使用繼承。
繼承要慎用,其使用場合僅限於你確信使用該技術有效的情況。一個判斷方法是,問一問自己是否需要從新類向基類進行向上轉型。如果是必須的,則繼承是必要的。反之則應該好好考慮是否需要繼承。《Java程式設計思想》
只有當子類真正是超類的子型別時,才適合用繼承。換句話說,對於兩個類A和B,只有當兩者之間確實存在
is-a
關係的時候,類B才應該繼續類A。《Effective Java》
相關文章
- Java中的繼承與組合Java繼承
- JavaScript中的繼承和組合JavaScript繼承
- 【Java】繼承、抽象、組合Java繼承抽象
- 菜鳥譯文(一)——Java中的繼承和組合Java繼承
- 深入理解JavaScript中的類繼承JavaScript繼承
- 深入理解原型鏈和繼承原型繼承
- 繼承與組合繼承
- prefer 組合 to 繼承繼承
- 深入理解javascript中的繼承機制(1)JavaScript繼承
- 組合優於繼承繼承
- js 組合繼承詳解JS繼承
- 深入理解javascript原型和閉包(6)——繼承JavaScript原型繼承
- 這樣理解,java繼承中多型的屬性和方法Java繼承多型
- java中的繼承Java繼承
- Docker的組合優於繼承 - frankelDocker繼承
- 類的組合與繼承——作業繼承
- java中繼承Java中繼繼承
- java 繼承多型的一些理解和不理解Java繼承多型
- javascript組合繼承的基本原理JavaScript繼承
- 深入理解JavaScript原型鏈與繼承JavaScript原型繼承
- Java 8 預設方法和多繼承深入解析Java繼承
- YTU-OJ-繼承與組合繼承
- Java繼承和介面Java繼承
- python物件導向的繼承-組合-02Python物件繼承
- 組合思維與繼承思維的不同繼承
- 【設計模式】如何用組合替代繼承設計模式繼承
- Python面試題1:類變數在繼承中的深入理解Python面試題變數繼承
- 從babel實現es6類的繼承來深入理解js的原型及繼承Babel繼承JS原型
- JavaScript中的原型和繼承JavaScript原型繼承
- Java的繼承Java繼承
- 換個角度就很好深入理解的js繼承JS繼承
- 深入JavaScript繼承原理JavaScript繼承
- 組合和繼承怎麼整合一個效能較好的專案繼承
- Java繼承Java繼承
- C中的繼承和多型繼承多型
- Java之繼承和抽象類Java繼承抽象
- JAVA中的註解可以繼承嗎?Java繼承
- java之繼承中的構造方法Java繼承構造方法