Scala的本地函數(shù):將私有方法轉(zhuǎn)換為本地方法
上節(jié)中processFile方法的建立演示了函數(shù)式編程風(fēng)格的一個重要設(shè)計(jì)原則:程序應(yīng)該被解構(gòu)成若干小的函數(shù),每個完成一個定義良好的任務(wù)。單個函數(shù)經(jīng)常很小。這種風(fēng)格的好處是它給了程序員許多可以靈活組裝成更復(fù)雜事物的建造模塊。每個小塊應(yīng)該充分簡化到足以單獨(dú)理解。
這種方式的一個問題是所有這些幫助函數(shù)的名稱會污染程序的命名空間。在解釋器里這不太成問題,但是一旦函數(shù)被打包成可復(fù)用的類和對象,就最好對類的客戶隱藏幫助函數(shù)。它們經(jīng)常不能獨(dú)立表達(dá)什么意思,并且如果之后用其它方式重寫類的話,也常會想保持能刪掉幫助方法的足夠的靈活度。
Java里,達(dá)成這個目的的主要工具是private方法。這種私有方法的方式在Scala里同樣有效,如代碼8.1里描述的,但是Scala提供了另一種方式:你可以把函數(shù)定義在另一個函數(shù)中。就好象本地變量那樣,這種本地函數(shù)僅在包含它的代碼塊中可見。以下是一個例子:
在這個例子中,我們通過把私有方法,processLine,轉(zhuǎn)換為本地方法,processFile,重構(gòu)了展示在代碼8.1中原本的LongLines版本。為了做到這點(diǎn)我們?nèi)サ袅藀rivate修飾符,它僅能應(yīng)用于方法(并且僅被方法需要),然后把processLine的定義放在processFile的定義里。作為本地函數(shù),processLine的范圍局限于processFile之內(nèi),外部無法訪問。
- def processFile(filename: String, width: Int) {
- def processLine(filename:String, width:Int, line:String) {
- if (line.length > width) print(filename+": "+line)
- }
- val source = Source.fromFile(filename)
- for (line < - source.getLines) {
- processLine(filename, width, line)
- }
- }
既然processLine被定義在processFile里,另一個改善變?yōu)榭赡芰恕U堊⒁鈌ilename和width是怎樣不改變地傳入到幫助函數(shù)中。這不是必須的,因?yàn)楸镜睾瘮?shù)可以訪問包含它們的函數(shù)的參數(shù)。你可以直接使用外部processLine函數(shù)的參數(shù),如代碼8.2所示:
代碼 8.2 帶本地processLine方法的LongLines
- import scala.io.Source
- object LongLines {
- def processFile(filename: String, width: Int) {
- def processLine(line: String) {
- if (line.length > width)
- print(filename +": "+ line)
- }
- val source = Source.fromFile(filename)
- for (line < - source.getLines)
- processLine(line)
- }
- }
更簡單了,不是嗎?這種對外層函數(shù)的參數(shù)的使用是Scala提供的通用嵌套的很平常也很有用的例子。7.7節(jié)描述的嵌套和作用域應(yīng)用于所有的Scala架構(gòu),包括函數(shù)。這是一個簡單的原則,不過非常強(qiáng)大,尤其在擁有函數(shù)作為第一類值的語言中。
【相關(guān)閱讀】
- Scala中定義函數(shù)的方法:method
- 繼續(xù)領(lǐng)悟函數(shù)式:Scala指令式風(fēng)格代碼的重構(gòu)
- 學(xué)習(xí)Scala的變量范圍
- Scala:match表達(dá)式、break和continue
- 學(xué)習(xí)Scala:使用try-catch表達(dá)式處理異常