你已经看到了如何创建闭包及如果使用闭包,这个功能非常强大但是使用起来仍会很简单。
这一节来看看下层的东西,以加深你在使用这种简单的方式创建闭包的时候对后台工作 原理的理解,我们仔细看看在闭包的内部有什么数据和方法可以使用,使用 this 引用到的是什么,及怎样用你的知识来测试设计的一个典型例子和测试任何语言表达式。
这有点技术难度,你在第一次阅读的时候可以安全的跳过,不管怎样,在适当的时候你也许想来看看这一节并且了解 groovy 是如何提供这些聪明的技巧的。事实上,明白细节经常能让你自己想出特别优美的解决方案。
那么在一个闭包内什么是可用的,这个范围包括:
什么样的本地变量可以被访问
this(当前对象)引用到的是什么
什么属性和方法是可以访问的
我们以已经看到过的例子来说明,为了说明,我们重新来看看循环 10 次做一些事情的代码:def x = 0
10.times {
x++
}
assert x == 10
很明显,传递给 times 方法的闭包可以访问变量 x,在声明闭包的时候本地变量是可以 访问的,记住:花括号显示了闭包声明的时间,不是执行的时间。在闭包的声明期间,闭包以对变量 x 进行读和写操作。
这引起第二个想法:闭包在执行的时候想必也要访问 x,否则 x 是如何递增的呢?
但是闭包被传递给 times 方法,这是在一个值为 10 的 Integer 上进行的调用,这个方法,依次回 调我们的闭包,但是 times 方法没有知道变量 x 的机会,因此它不能传递 x 给闭包,想必也知道闭包使用了 x 变量。
唯一能使这工作的途径可能是闭包在它的生命周期里以某种方式记住了它的工作上下文环境,当调用它的时候,闭包可以在它的原始上下文中工作。
这种生命周期的上下文需要闭包记住相应的一个引用,不是一个复制品,如果工作上下文是原始上下文的一个复制品,从闭包中是没有办法改变原始上下文的。但是我们的例子清晰的显示了改变了 x 的值——否则断言将失败,因此,生命周期上下文必须被引用。