關於Java中的繼承和組合的一個錯誤使用的例子

關於Java中的繼承和組合的一個錯誤使用的例子

相信絕大多數人都比較熟悉Java中的「繼承」和「組合」這兩個東西,本篇文章就主要就這兩個話題談論一下。若是我某些地方寫的不對,或者比較幼稚,論證不清晰,歡迎你們留言指正。code

什麼是「組合」和「繼承」

假設有2個class:AB:繼承

  • 若是class A extends B 那麼咱們就說A繼承B,A是子類,B是父類,這種狀況就是繼承。
  • 若是A中有一個屬性的類型爲B,那麼咱們就說這種狀況就是組合。

分別在什麼狀況下使用

回想一些咱們通常會在什麼狀況下考慮這兩個東西呢?我大體想了一下,每每會有以下的場景:it

  • 公用代碼
  • 爲了代表事物之間的「共性」或者說僅僅爲了「泛型」,抽取abstract class或者interface

我想來想去,好像真的只有這兩種狀況了,可是這兩種狀況有特別的有關聯,好比說公用代碼這個事情,其實abstract classinterface(Java 8中的default method)均可以達到。table

好吧,說了這麼多屁話,我就直接拋出個人觀點吧,歡迎拍磚:class

  • 若是你僅僅想公用代碼,並且使用這些公用代碼的class或者method並無很明顯的聯繫,那麼就請使用組合。
  • 若是若干個class或者其method有比較明顯的聯繫,那麼請抽取一個abstract class或者interface
  • 慎用「屬性繼承」的特性,建議子類明確複寫所須要的父類的屬性。這一點尤其重要,後續會有一個例子來講明這種狀況的不利面。

反面教材

比較常見的一個例子:咱們在實際的項目中,每每會定義好的的POJO或者說model,而這些model每每都會有一些名詞和類型相同的屬性,好比:泛型

// db table primary key
private int id;

很常見吧,可是我在實際工做中遇到過很多的同事,系統定義一個名稱可能爲BaseModel或者RootModel的類,把上面的屬性id放在裏面,而後整個項目中全部的model都繼承這個BaseModdel類。不知道大家是否遇到過這樣的同事?大家覺的這樣寫能有什麼好處和壞處呢?搜索

先說好處吧,若是非要說能帶來什麼好處的話,除了少敲幾下鍵盤,在子類中少些了這些屬性之外,沒看見有啥實質性的好處。可是卻爲項目後續的維護帶來了很麻煩的事情。model

而後說這種寫法的潛在問題吧:im

某一天,由於一些緣由,你想找子類A(繼承了BaseModel)中的屬性id在項目中的哪些地方使用

機智的你熟練的使用起了IDE中的find usages,而後你就會發現你找到的使用位置很是的多,並且好多壓根不是你關心的。可是沒辦法,你也搜索到了其餘的繼承了BaseModel的類的屬性id的使用位置。若是項目不大,可能搜索到的熟練比較少,若是項目大了一點呢?當搜索熟練超過了50處,你接下來會怎麼作?

  • 一個一個看搜索出來的代碼,看了十幾二十個開始噴,而後繼續一個一個往下找?
  • 直接開始噴,而後在一個一個看搜索出來的代碼?

如何避免出現這種狀況呢,那就是不要使用相似這種BaseModel的方式來使用屬性繼承。固然爲了嚴謹期間,我仍是須要詳細說一下這個意思,我並無徹底反對屬性繼承哦,明確一下:

我反對的是整個項目全部的model繼承一個BaseModel,而後把公用屬性放在BaseModel中

的這種想法,注意是整個項目的

後記

上面的反面教材的例子我我的常常會遇見,因此單獨拿出來講一下,我不肯定在你們的項目中是否出現過這種狀況。反正我已經被同事的這種寫法坑過好多回了。

至於「組合」和「繼承」其餘相關的常見錯誤,我暫時還沒想好(至少我覺的應該沒人會犯),若是我後續想清楚了,或者讀者朋友們有其餘的建議但願能夠留言交流一下哈。

相關文章
相關標籤/搜索