-
Notifications
You must be signed in to change notification settings - Fork 0
Closures
Groovy closures are true closures, with access to the variables in the context in which they are defined. They are:
-
Contained in braces
-
They are functions.
-
But they are also instances of the Closure class.
-
Used in callbacks
-
The default parameter (if you do not provide parameters) is
it.[1,2,3].each { println it }
Syntactically, closures look a lot like lambdas, and they can be passed as parameters to another function. In other words, they are first-class objects. However, closures are instances of the Closure class, making them very different from Java 8 lambdas.
In addition, delegation is a key concept in Groovy closures which has no equivalent in lambdas. The ability to change the delegate or change the delegation strategy of closures make it possible to design beautiful domain specific languages (DSLs) in Groovy.
{ <type> param1, <type> param2 ... ->
//Body
}- Again, parameters are optional.
- If no parameters are listed, the default parameter is
it. - Parameters, if present, are listed (comma-separated) immediately after the first brace, on the first line of the closure, and followed by a arrow.
- The code body begins on the next line.
- The output of the last line is the return value, with or without the
returnstatement.
Closures can be invoked like any other function:
closureName(<params...>)Alternatively, closures can be invoked with the call method of the Closure class:
def c = { 123 } // returns 123
assert c() == 123 // true
assert c.call() == 123 // trueFor a function/closure to take a Closure as a parameter, that parameter must be declared as the Closure datatype.1
Example
private defaultResponseHandler = { resp, reader ->
assert resp.status == 200
println "My response handler got response: ${resp.statusLine}"
println "Response length: ${resp.headers.'Content-Length'}"
System.out << reader // print response reader
}
void fetchContent(String path, Closure c = defaultResponseHandler){
connect path, TEXT, c
}In this case, from my HttpClient, I make the Closure parameter optional by giving it a default value. In either case, the closure works as a callback.
To understand the concept of delegate, we must first explain the meaning of this inside a closure. A closure actually defines 3 distinct things:
-
thiscorresponds to the enclosing class where the closure is defined -
ownercorresponds to the enclosing object where the closure is defined, which may be either a class or a closure -
delegatecorresponds to a third party object where methods calls or properties are resolved whenever the receiver of the message is not defined