什么是閉包
一個groovy閉包就像一個代碼塊或者方法指針,他是定義然后執行的一段代碼,但是他有一些特性:隱含變量,支持自由變量,支持currying 。
我們先來看看一些例子:
1 |
def clos = { println "hello!" } |
2 |
3 |
println "Executing the Closure:" |
4 |
clos() //prints "hello!" |
在上面的例子中”hello!”是因為調用clos()函數才打印出來的,而不是在定義的時候打印出來的。
參數
閉包的參數在->之前列出,比如:
1 |
def printSum = { a, b -> print a+b } |
2 |
printSum( 5 , 7 ) //prints "12" |
如果閉包的參數是少於2個的話,那么 ->是可以省略的。
Parameter notes
A Closure without -> , i.e. {} , is a Closure with one argument that is implicitly named as ‘it’. (see below for details) In some cases, you need to construct a Closure with zero arguments, e.g. using GString for templating, defining EMC Property etc. You have to explicity define your Closure as { -> } instead of just { }
You can also use varargs as parameters, refer to the Formal Guide for details. A JavaScript-style dynamic args could be simulated, refer to the Informal Guide.
自由變量
閉包能引用在參數列表中沒有列出的變量,這些變量成為自由變量,他們的作用范圍在他們定義的范圍內:
1 |
def myConst = 5 |
2 |
def incByConst = { num -> num + myConst } |
3 |
println incByConst( 10 ) // => 15 |
另外一個例子:
1 |
def localMethod() { |
2 |
def localVariable = new java.util.Date() |
3 |
return { println localVariable } |
4 |
} |
5 |
6 |
def clos = localMethod() |
7 |
8 |
println "Executing the Closure:" |
9 |
clos() //prints the date when "localVariable" was defined |
隱式變量
it
如果你有一個閉包但是只有一個參數,那么你可以省略這個參數,比如:
1 |
def clos = { print it } |
2 |
clos( "hi there" ) //prints "hi there" |
this, owner, and delegate
this : 和java中是一樣的, this
refers to the instance of the enclosing class where a Closure is defined
owner : the enclosing object (this
or a surrounding Closure)
delegate : by default the same as owner
, but changeable for example in a builder or ExpandoMetaClass
1 |
class Class1 { |
2 |
def closure = { |
3 |
println this. class .name |
4 |
println delegate. class .name |
5 |
def nestedClos = { |
6 |
println owner. class .name |
7 |
} |
8 |
nestedClos() |
9 |
} |
10 |
} |
11 |
12 |
def clos = new Class1().closure |
13 |
clos.delegate = this |
14 |
clos() |
15 |
/* prints: |
16 |
Class1 |
17 |
Script1 |
18 |
Class1$_closure1 */ |
閉包作為方法參數
當一個方法使用閉包作為最后一個參數的話,那么就可以內嵌一個閉包,比如:
1 |
def list = [ 'a' , 'b' , 'c' , 'd' ] |
2 |
def newList = [] |
3 |
4 |
list. collect ( newList ) { |
5 |
it.toUpperCase() |
6 |
} |
7 |
println newList // ["A", "B", "C", "D"] |
在上面的collect方法中,他接受一個一個List和閉包,上面的代碼等價於下面的代碼:
1 |
def list = [ 'a' , 'b' , 'c' , 'd' ] |
2 |
def newList = [] |
3 |
4 |
def clos = { it.toUpperCase() } |
5 |
list. collect ( newList, clos ) |
6 |
7 |
assert newList == [ "A" , "B" , "C" , "D" ] |
更多的信息:
Groovy繼承了 java.lang.Object
並且許多的 Collection
和Map
的許多方法都接受閉包作為參數的 See GDK Extensions to Object for practical uses of Groovy's Closures.
See Also: