在Scala中定義無參數(shù)方法
作為下一步,我們將向Element添加顯示寬度和高度的方法,展示在代碼10.2中。height方法返回contents里的行數(shù)。width方法返回***行的長度,或如果元素沒有行記錄,返回零。(也就是說你不能定義一個高度為零但寬度不為零的元素。)
- abstract class Element {
- def contents: Array[String]
- def height: Int = contents.length
- def width: Int = if (height == 0) 0 else contents(0).length
- }
代碼 10.2 定義無參數(shù)方法width和height
51CTO編輯推薦:Scala編程語言專題
請注意Element的三個方法沒一個有參數(shù)列表,甚至連個空列表都沒有。例如,代之以:
方法定義了不加括號的:
- def width(): Int
這種無參數(shù)方法在Scala里是非常普通的。相對的,帶有空括號的方法定義,如def height(): Int,被稱為空括號方法:empty-paren method。推薦的慣例是在沒有參數(shù)并且方法僅通過讀含有對象的方式訪問可變狀態(tài)(專指其不改變可變狀態(tài))時(shí),使用無參數(shù)方法。這個慣例支持統(tǒng)一訪問原則:uniform access principle,Meyer,面向?qū)ο筌浖?gòu)造【Mey00】就是說客戶代碼不應(yīng)受通過字段還是方法實(shí)現(xiàn)屬性的決定的影響。例如,我們可以選擇把width和height作為字段而不是方法來實(shí)現(xiàn),只要簡單地在每個實(shí)現(xiàn)里把def修改成val即可:
- def width: Int
兩組定義從客戶的觀點(diǎn)來看是完全相同的。唯一的差別是與的訪問或許稍微比方法調(diào)用要快,因?yàn)樽侄沃翟陬惐怀跏蓟臅r(shí)候被預(yù)計(jì)算,而方法調(diào)用在每次調(diào)用的時(shí)候都要計(jì)算。換句話說,字段在每個Element對象上需要更多的內(nèi)存空間。因此類的使用概況,屬性表達(dá)成字段還是方法更好,決定了其實(shí)現(xiàn),并且這個概況還可以隨時(shí)改變。重點(diǎn)是Element類的客戶不應(yīng)在其內(nèi)部實(shí)現(xiàn)改變的時(shí)候受影響。
- abstract class Element {
- def contents: Array[String]
- val height = contents.length
- val width =
- if (height == 0) 0 else contents(0).length
- }
特別是如果類的字段變成了訪問函數(shù),且訪問函數(shù)是純的,就是說它沒有副作用并且不依賴于可變狀態(tài),那么類Element的客戶不需要被重寫??蛻舳疾粦?yīng)該需要關(guān)心這些。
目前為止一切良好。但仍然有些瑣碎的復(fù)雜的東西要去做以協(xié)同Java處理事情的方式。問題在于Java沒有實(shí)現(xiàn)統(tǒng)一訪問原則。因此Java里是string.length(),不是string.length(盡管是array.length,不是array.length())。不用說,這讓人很困惑。
為了在這道缺口上架一座橋梁,Scala在遇到混合了無參數(shù)和空括號方法的情況時(shí)很大度。特別是,你可以用空括號方法重載無參數(shù)方法,并且反之亦可。你還可以在調(diào)用任何不帶參數(shù)的方法時(shí)省略空的括號。例如,下面兩行在Scala里都是合法的:
原則上Scala的函數(shù)調(diào)用中可以省略所有的空括號。然而,在調(diào)用的方法表達(dá)的超過其接收調(diào)用者對象的屬性時(shí),推薦仍然寫一對空的括號。例如,如果方法執(zhí)行了I/O,或?qū)懭肟芍匦沦x值的變量(var),或讀出不是接受調(diào)用者的字段的var,無論是直接的還是非直接的通過使用可變對象,那么空括號是合適的。這種方式是讓參數(shù)列表扮演一個可見的線索說明某些有趣的計(jì)算正通過調(diào)用被觸發(fā)。例如:
- Array(1, 2, 3).toString
- "abc".length
- "hello".length // 沒有副作用,所以無須()
- println() // ***別省略()
總結(jié)起來,Scala里定義不帶參數(shù)也沒有副作用的方法為無參數(shù)方法,也就是說,省略空的括號,是鼓勵的風(fēng)格。另一方面,永遠(yuǎn)不要定義沒有括號的帶副作用的方法,因?yàn)槟菢拥脑挿椒ㄕ{(diào)用看上去會像選擇一個字段。這樣你的客戶看到了副作用會很奇怪。相同地,當(dāng)你調(diào)用帶副作用的函數(shù),請確信寫這個調(diào)用的時(shí)候包括了空的括號。另一種考慮這個問題的方式是,如果你調(diào)用的函數(shù)執(zhí)行了操作,使用括號,但如果僅提供了對某個屬性的訪問,省略括號。
【相關(guān)閱讀】