闭包 Closures,最初接触大概是在看 Swift 文档的时候,但是似是而非,好像明白了,好像就没彻底明白,记得当时也查了一些资料,终究是没彻底弄清楚。
后来看 Kotlin 也谈到闭包,看下 Kotlin 里的定义:
A lambda expression or anonymous function (as well as a local function and an object expression) can access its closure, i.e. the variables declared in the outer scope.
Lambda 表达式或者匿名函数(以及局部函数和对象表达式) 可以访问其闭包,即在外部作用域中声明的变量。
好简洁啊,插个题外话,整个 Kotlin 文档的编排顺序,详细度都无法和 Swift 文档相比。
再来看看 Swift 的说明,它说闭包有三种形式:
- Global functions are closures that have a name and do not capture any values. 全局函数是一个有名字但不会捕获任何值的闭包。
- Nested functions are closures that have a name and can capture values from their enclosing function. 内嵌函数是一个有名字且能从其上层函数捕获值的闭包。
- Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context. 闭包表达式是一个轻量级语法所写的可以捕获其上下文中常量或变量值的没有名字的闭包。
第一种全局函数,不捕获任何值,也没什么好说的,第二种内嵌函数,这是最常见的类型,第三种其实就是 lambda 表达式,也相当于内嵌函数。
之所以想起写这篇文章,是因为前几周在阅读《函数式编程思维》时,读到里面讲到闭包,突然感觉明白了。
真是不懂的时候感觉好复杂,明白了以后感觉一两句话,不往底层深究的话,实在没什么可以说的。
书里说闭包是一种特殊的函数,暗地绑定了函数内部引用的全部变量。闭包在生成的时候,会把引用的变量全部圈到代码块的作用域里,封闭包围起来,故名『闭包』。
这里用 Swift 文档里的例子来说明
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
外部函数 makeIncrementer 的返回值类型是一个函数 incrementer,而 incrementer 函数本身并没有任何参数,runningTotal 和 amount 都是外部函数的。
当调用 makeIncrementer 返回一个函数时,依然可以调用这个返回的 incrementer 函数返回一个整数,因为 runningTotal 和 forIncrement 已经被它和自己绑定在一起了。每调用一次 runningTotal 的值就递增一个 forIncrement 的大小。
// 获得一个闭包实例
let incrementByTen = makeIncrementer(forIncrement: 10)
// 连续调用三次
incrementByTen()
//return a value of 10
incrementByTen()
//return a value of 20
incrementByTen()
//return a value of 30
// 获得另一个闭包
let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
// returns a value of 7
// 再次调用第一个闭包
incrementByTen()
// returns a value of 40
incrementBySeven 和 incrementByTen 互不影响。因为闭包的每个实例都保有自己的一份变量取值,包括私有变量。
网友评论