鍍金池/ 教程/ Scala/ 組合和繼承–使用組合還是繼承?
包對(duì)象
Ordered Trait
組合和繼承–定義 final 成員
基本數(shù)據(jù)類(lèi)型
Match 表達(dá)式
類(lèi)和對(duì)象 (三)
操作基本數(shù)據(jù)類(lèi)型
for 表達(dá)式
組合和繼承–重載成員函數(shù)和方法
類(lèi)和對(duì)象 (二)
組合和繼承–定義 factory 對(duì)象
組合和繼承–多態(tài)和動(dòng)態(tài)綁定
Trait 的基本概念
if 表達(dá)式
組合和繼承–抽象類(lèi)
函數(shù)–函數(shù)字面量的一些簡(jiǎn)化寫(xiě)法
while 循環(huán)
組合和繼承–使用組合還是繼承?
訪問(wèn)控制修飾符
Trait 示例–Rectangular 對(duì)象
組合和繼承–定義參數(shù)化成員變量
組合和繼承–定義無(wú)參數(shù)方法
類(lèi)和對(duì)象 (一)
函數(shù)–閉包
函數(shù)–類(lèi)成員函數(shù)
Scala 基本數(shù)據(jù)類(lèi)型的實(shí)現(xiàn)方法
try 表達(dá)式處理異常
選擇瘦接口還是胖接口設(shè)計(jì)?
組合和繼承–小結(jié)
創(chuàng)建新的控制結(jié)構(gòu)
使用 import
為訪問(wèn)控制修飾符添加作用域
Scala 的類(lèi)層次關(guān)系
類(lèi)和對(duì)象 (五)
傳名參數(shù)
柯里化函數(shù)
函數(shù)–頭等公民
組合和組合和繼承–定義 heighten 和 widen 函數(shù)
使用 Package–將代碼放入包中
隱含的 import
所有類(lèi)的公共子類(lèi)–底層類(lèi)型
進(jìn)一步 Scala
函數(shù)–局部函數(shù)
引用包中的代碼
組合和繼承–使用 override 修飾符
組合和繼承–實(shí)現(xiàn)類(lèi) Element 的 above,beside 和 toString()方法
類(lèi)和對(duì)象 (四)
函數(shù)–尾遞歸
沒(méi)有“break”和“continue”的日子
組合和繼承–調(diào)用基類(lèi)構(gòu)造函數(shù)
減低代碼重復(fù)
函數(shù)–函數(shù)–可變參數(shù),命名參數(shù),缺省參數(shù)
起步 Scala
組合和繼承–擴(kuò)展類(lèi)
函數(shù)–部分應(yīng)用的函數(shù)
開(kāi)始神奇的 Scala編程之旅
組合和繼承–概述
Trait 用來(lái)實(shí)現(xiàn)可疊加的修改操作

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

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

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

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

請(qǐng)看下面的類(lèi)層次關(guān)系圖:

http://wiki.jikexueyuan.com/project/scala-development-guide/images/14.png" alt="" />

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

 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?,F(xiàn)在它與 Array 有一個(gè)組合關(guān)系:在它自己的 contents 字段中持有一個(gè)字串?dāng)?shù)組的引用。有了 LineElement 的這個(gè)實(shí)現(xiàn),Element 的繼承層級(jí)現(xiàn)在如下圖所示:

http://wiki.jikexueyuan.com/project/scala-development-guide/images/15.png" alt="" />

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