Scala 組合和繼承–使用組合還是繼承?

2018-09-28 18:21 更新

組合和繼承–使用組合還是繼承?

前面我們說過,構(gòu)建新類的兩個(gè)基本方法是組合和繼承,如果你的主要目的是代碼重用,那么最好使用組合的方法構(gòu)造新類,使用繼承的方法構(gòu)造新類造成的可能問題是,無意的修改基類可能會破壞子類的實(shí)現(xiàn)。

關(guān)于繼承關(guān)系你可以問自己一個(gè)問題,是否它建模了一個(gè) is-a 關(guān)系。例如,說 ArrayElement 是 Element 是合理的。你能問的另一個(gè)問題是,是否客戶想要把子類類型當(dāng)作基類類型來用。

前一個(gè)版本中,LineElement 與 ArrayElement 有一個(gè)繼承關(guān)系,從那里繼承了 contents。現(xiàn)在它在 ArrayElement 的例子里,我們的確期待客戶會想要把 ArrayElement 當(dāng)作 Element 使用。

請看下面的類層次關(guān)系圖:

看著這張圖,問問上面的問題,是否感覺其中的任何關(guān)系有可疑嗎?尤其是,對你來說 LineElement 是 ArrayElement 是否顯而易見呢?你是否認(rèn)為客戶會需要把 LineElement 當(dāng)作 ArrayElement 使用?實(shí)際上,我們把 LineElement 定義為 ArrayElement 主要是想重用 ArrayElement 的 contents 定義。因此或許把 LineElement 定義為 Element 的直接子類會更好一些,就像這樣:

 class LineElement(s: String) extends Element {  
   val contents = Array(s)  
   override def width = s.length  
   override def height = 1 
  } 

前一個(gè)版本中,LineElemen t與 ArrayElement 有一個(gè)繼承關(guān)系,從那里繼承了 contents。現(xiàn)在它與 Array 有一個(gè)組合關(guān)系:在它自己的 contents 字段中持有一個(gè)字串?dāng)?shù)組的引用。有了 LineElement 的這個(gè)實(shí)現(xiàn),Element 的繼承層級現(xiàn)在如下圖所示:

因此在選用組合還是通過繼承來構(gòu)造新類時(shí),需要根據(jù)需要選擇合適的方法。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號