| |
| 1 Closures |
| |
| Closures are a powerful way of passing around blocks of executable code. |
| Think of closures as being like anonymous inner classes in Java that have only a single (anonymous) method. |
| |
| Closures can be used as an alternative to using iterators; where the container is in full control. |
| |
| {code:groovy} |
| [1, 2, 3, 4].each { println(it) } |
| {code} |
| |
| Using closures can make the handling of exceptions and the closing of resources much simpler. |
| For a good example of this see {link:Groovy SQL|sql.html} |
| |
| 1.1 Closures compared to anonymous inner classes |
| |
| One difference from anonymous inner classes in Java is that Groovy supports ~~true closures~~ |
| where state can be passed into and out of closures. Any local variables in scope |
| when the closure is created can be used and modified and any variables created within |
| the closure are visible outside as local variables. No 'final' keyword is required |
| like with Java and annonymous inner classes. |
| |
| Consider the following code |
| |
| {code:groovy} |
| count = 0 |
| [1, 2, 3, 4].each { count += it; last = it } |
| println("the sum is ${count} and the last item was ${last}") |
| {code} |
| |
| Notice that ~~count~~ goes from the outer scope to the inner scope and back out again after being modified. |
| The ~~last~~ variable goes from inside scope out. |
| |
| 1.1 Closures are normal objects |
| |
| Closures are objects that can be passed around and called on demand. So you can do things like this |
| |
| {code:groovy} |
| c = { println("Hello ${it}") } |
| c('James') |
| c('Bob') |
| {code} |
| |
| Each closure is compiled to a new class which is derived from {link:Closure|http://groovy.codehaus.org/apidocs/groovy/lang/Closure.html}. |
| The above is syntax sugar for. |
| |
| {code:groovy} |
| c = { println("Hello ${it}") } |
| c.call('James') |
| c.call('Bob') |
| {code} |
| |
| 1.1 Closure parameters |
| |
| A closure can take an arbitrary number of parameters like normal Java/Groovy methods. |
| By default a closure takes a single parameter whose name defaults to being called 'it'. You |
| can specify any name(s) you wish using a parameter list clause at the start of the closure |
| declaration. |
| |
| {code:groovy} |
| c = { param | println("Hello ${param}") } |
| c('James') |
| c('Bob') |
| {code} |
| |
| {code:groovy} |
| c = { a, b, c | println("Hello ${a} ${b} ${c}") } |
| c('cheese', 234, 'gromit') |
| {code} |
| |
| Here is another example of using closures with 2 parameters with the inject() method |
| which is useful for aggregation. |
| |
| {code:groovy} |
| value = [1, 2, 3].inject('counting: ') { str, item | str + item } |
| assert value == "counting: 123" |
| |
| value = [1, 2, 3].inject(0) { count, item | count + item } |
| assert value == 6 |
| {code} |
| |
| You can see more documentation on closures {link:here|http://wiki.codehaus.org/groovy/BlocksAndClosures} |