W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
到目前為止我們介紹的函數(shù)都只引用到傳入的參數(shù),假如我們定義如下的函數(shù):
(x:Int) => x + more
這里我們引入一個(gè)自由變量 more。它不是所定義函數(shù)的參數(shù),而這個(gè)變量定義在函數(shù)外面,比如:
var more =1
那么我們有如下的結(jié)果:
scala> var more =1
more: Int = 1
scala> val addMore = (x:Int) => x + more
addMore: Int => Int = <function1>
scala> addMore (100)
res1: Int = 101
這樣定義的函數(shù)變量 addMore 成為一個(gè)“閉包”,因?yàn)樗玫胶瘮?shù)外面定義的變量,定義這個(gè)函數(shù)的過(guò)程是將這個(gè)自由變量捕獲而構(gòu)成一個(gè)封閉的函數(shù)。有意思的是,當(dāng)這個(gè)自由變量發(fā)生變化時(shí),Scala 的閉包能夠捕獲到這個(gè)變化,因此 Scala 的閉包捕獲的是變量本身而不是當(dāng)時(shí)變量的值。
比如:
scala> more = 9999
more: Int = 9999
scala> addMore ( 10)
res2: Int = 10009
同樣的,如果變量在閉包在發(fā)生變化,也會(huì)反映到函數(shù)外面定義的閉包的值。比如:
scala> val someNumbers = List ( -11, -10, -5, 0, 5, 10)
someNumbers: List[Int] = List(-11, -10, -5, 0, 5, 10)
scala> var sum =0
sum: Int = 0
scala> someNumbers.foreach ( sum += _)
scala> sum
res4: Int = -11
可以看到在閉包中修改 sum 的值,其結(jié)果還是傳遞到閉包的外面。
如果一個(gè)閉包所訪問的變量有幾個(gè)不同的版本,比如一個(gè)閉包使用了一個(gè)函數(shù)的局部變量(參數(shù)),然后這個(gè)函數(shù)調(diào)用很多次,那么所定義的閉包應(yīng)該使用所引用的局部變量的哪個(gè)版本呢? 簡(jiǎn)單的說(shuō),該閉包定義所引用的變量為定義該閉包時(shí)變量的值,也就是定義閉包時(shí)相當(dāng)于保存了當(dāng)時(shí)程序狀態(tài)的一個(gè)快照。比如我們定義下面一個(gè)函數(shù)閉包:
scala> def makeIncreaser(more:Int) = (x:Int) => x + more
makeIncreaser: (more: Int)Int => Int
scala> val inc1=makeIncreaser(1)
inc1: Int => Int = <function1>
scala> val inc9999=makeIncreaser(9999)
inc9999: Int => Int = <function1>
scala> inc1(10)
res5: Int = 11
scala> inc9999(10)
res6: Int = 10009
當(dāng)你調(diào)用 makeIncreaser(1)時(shí),你創(chuàng)建了一個(gè)閉包,該閉包定義時(shí) more的值為 1,而調(diào)用 makeIncreaser(9999)所創(chuàng)建的閉包的 more 的值為 9999。此后你也無(wú)法修改已經(jīng)返回的閉包的 more 的值。因此 inc1 始終為加一,而 inc9999 始終為加 9999。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: