不带自由变量的函数字面量被称为封闭项,依照函数字面量在运行时创建的对象被称为闭包
自由变量
(x:Int) => x + more
完整示例:
scala> var more =1 more: Int = 1 scala> val addMore = (x:Int) => x + more addMore: Int => Int = <function1> scala> addMore (100) res1: Int = 101
此处函数变量 addMore 称为一个“闭包”:因为它引用函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数。
当自由变量发生变化时,Scala 的闭包能够捕获到这个变化,因为 Scala 的闭包捕获的是变量本身而不是当时变量的值。
scala> more = 9999 more: Int = 9999 scala> addMore ( 10) res2: Int = 10009
同样,如果变量在闭包发生变化,也会反映到函数外面定义的变量
scala> val numbers = List ( -11, -10, -5, 0, 5, 10) numbers: List[Int] = List(-11, -10, -5, 0, 5, 10) scala> var sum =0 sum: Int = 0 scala> numbers.foreach(sum += _)
scala> sum res4: Int = -11
一个闭包如果使用了一个函数的参数,然后该函数被多次调用,那么闭包所引用的变量为定义该闭包时变量的值
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
定义闭包时相当于保存了当时程序状态的一个快照
调用 makeIncreaser(1) 时所创建闭包引用的 more 的值为 1,而调用 makeIncreaser(9999) 时所创建闭包引用的 more 的值为 9999。