什么是闭包(Groovy)

    博客分类:

  • Grails & Groovy
GroovyJavaCC++C#
Groovy的闭包就像一个代码段或者说方法指针。它是一段被定义并在稍后的时点上运行的代码。

Simple Example

Java代码
  1. defclos={println"hello!}
def clos = { println "hello! }
Java代码
  1. 示例:defclos={println"hello!}
  2. println"Executingtheclosure:"
  3. clos()
示例: def clos = { println "hello!}
println "Executing the closure:"
clos()  

注意在上面的例子中,"hello"在闭包被调用的时候才打印出来,而不是在定义的时候。

Closures may be "bound" to variables within the scope where they are defined:

闭包可以与在特定范围内定义的变量绑定起来(这句不知翻译的对错,请看原文)

Java代码
  1. deflocalMethod(){
  2. deflocalVariable=newjava.util.Date()
  3. return{printlnlocalVariable}
  4. }
  5. defclos=localMethod()
  6. println"Executingtheclosure:"
  7. clos()//打印出当localVariables被创建时的时间
def localMethod() {
def localVariable = new java.util.Date()
return { println localVariable }
}
def clos = localMethod()
println "Executing the closure:"
clos()     //打印出当localVariables被创建时的时间

参数:

闭包的参数在->之前被列出,比如

Java代码
  1. defclos={a,b->printa+b}
  2. clos(5,7)//prints"12"
def clos = { a, b -> print a+b }
clos( 5, 7 )                       //prints "12"

-> 这个符号是可选的,当你定义的闭包的参数小于两个时就可将其省略

隐含的变量

在闭包中,有几个变量有着特别的含义

it(注意是小写):

如果你的闭包定义仅含有一个参数,可以将其省略,Groovy自动用it来代替

比如:

Java代码
  1. defclos={printit}
  2. clos("hithere")//prints"hithere"
def clos = { print it }
clos( "hi there" )              //prints "hi there"

this, owner, 和 delegate

this : 如同在Java中一样,this 代表闭包被定义的类

owner : 包含闭包的对象,有可能是定义闭包的类或者是另外一个闭包

delegate : 默认与owner相同,but changeable for example in a builder or ExpandoMetaClass

Java代码
  1. Example:
  2. classClass1{
  3. defclosure={
  4. printlnthis.class.name
  5. printlndelegate.class.name
  6. defnestedClos={
  7. printlnowner.class.name
  8. }
  9. nestedClos()
  10. }
  11. }
  12. defclos=newClass1().closure
  13. clos.delegate=this
  14. clos()
  15. /*prints:
  16. Class1
  17. Script1
  18. Class1$_closure1*/
Example:
class Class1 {
def closure = {
println this.class.name
println delegate.class.name
def nestedClos = {
println owner.class.name
}
nestedClos()
}
}
def clos = new Class1().closure
clos.delegate = this
clos()
/*  prints:
Class1
Script1
Class1$_closure1  */

作为方法参数的闭包

当一个方法的最后一个参数是闭包的时候,我们可以将闭包紧随其后定义,如

Java代码
  1. deflist=['a','b','c','d']
  2. defnewList=[]
  3. list.collect(newList){
  4. it.toUpperCase()
  5. }
  6. printlnnewList//["A","B","C","D"]
def list = ['a','b','c','d']
def newList = []
list.collect( newList ) {
it.toUpperCase()
}
println newList           //  ["A", "B", "C", "D"]

上一个例子也可以用下面的方法实现,就是稍显冗长。

Java代码
  1. deflist=['a','b','c','d']
  2. defnewList=[]
  3. defclos={it.toUpperCase()}
  4. list.collect(newList,clos)
  5. assertnewList==["A","B","C","D"]
def list = ['a','b','c','d']
def newList = []
def clos = { it.toUpperCase() }
list.collect( newList, clos )
assert newList == ["A", "B", "C", "D"]

更多:

Groovy 用很多可以接受闭包作为参数的方法扩展了java.lang.Object

上文提到的 collect 就是这样一个例子

collect(Collection collection) {closure} 返回一个集合,并将该集合的每一项添加到给定的集合中

发表回复