A closure in Groovy is an open, anonymous, block of code that can take arguments, return a value and be assigned to a variable. Groovy uses closures to specify a code to be executed each time and adds the extra methods ( each, any, every, find, findAll, collect and so forth) to the collection classes to make them readily available.
See here for more information on Closures.
On this page:
Defining a closure
Simple declaration: The following example shows a simple closure syntax. When there is only one parameter passed into closure, its declaration is optional.
Code Block |
---|
language | groovy |
---|
linenumbers | true |
---|
|
def log = ''
(1..10).each { counter -> log += counter }
log == "12345678910"
//it variable that needs no declaration
def log = ""
(1..10).each { log += it }
log == "12345678910" |
Using assignments for declaration: A second way of declaring a closure is to directly assign it to a variable.
Code Block |
---|
language | groovy |
---|
linenumbers | true |
---|
|
//Assigning a closure to a variable
Closure printer = { line -> println line }
printer instanceof Closure //returns true
//Empty closure
def emptyClosure = {}
emptyClosure instanceof Closure //returns true
//Assignment to the return value of a method
def Closure getPrinter() {
return{ line -> println line }
}
getPrinter() instanceof Closure //returns true |
Referring to methods as closures: Declaring a closure is to reuse something that is already declared a method. Groovy lets you reuse the code you already have in methods but as a closure.
Code Block |
---|
language | groovy |
---|
linenumbers | true |
---|
|
//Method closure assignment statement
def c = reference.&someMethod
//Different implementations are called based on argument types
class MultiMethodSample {
int mysteryMethod (String value) {
return value.length()
}
int mysteryMethod (List list) {
return list.size()
}
int mysteryMethod (int x, int y) {
return x+y
}
}
MultiMethodSample instance = new MultiMethodSample()
Closure multi = instance.&mysteryMethod
multi("Groovy in JMWE") == 14
multi(["a","Red",3.5]) == 3
multi(5,13) == 18 |
See below for an example that shows all of these ways of creating and using closures
Code Block |
---|
language | groovy |
---|
linenumbers | true |
---|
|
Map map = ['a':1, 'b':2]
//Closure passed as parameter directly
map.each{key, value ->
map[key] = value * 2
}
map
//Assign a closure object to a variable and call it
doubler = {key, value ->
map[key] = value * 2
}
map.each(doubler)
//Use of reference.&operator
def doubleMethod(entry){
entry.value = entry.value * 2
}
doubler = this.&doubleMethod
map.each(doubler) |
Calling a closure
A closure, as an anonymous block of code, can be called like any other method.
Code Block |
---|
language | groovy |
---|
linenumbers | true |
---|
|
def code = { 1234 }
code() == 1234
code.call() == 1234
//int as a parameter
def numberIsOdd = { int i -> i%2 !=0 }
numberIsOdd(3) == true
numberIsOdd.call(4) == false
//Same closure with implicit parameter it
def numberIsOdd = { it%2 !=0 }
numberIsOdd(3) == true
numberIsOdd.call(4) == false |
Parameters in a Closure
Parameters of closures follow the same principle as parameters of regular methods: an optional type, a name, an optional default value. They are separated with commas. It is possible for a closure to declare variable number of arguments. See the examples below.
Code Block |
---|
language | groovy |
---|
linenumbers | true |
---|
|
//Two Explicit types arguments
def closure = {int a, int b ->
a + b
}
//Two arguments
def closure = {a,b ->
a + b
}
//Two arguments with one default
def closure = {int a, b = 5 ->
a + b
}
//One Explicit type argument
def closure = {String name ->
it.toUpperCase()
}
//One argument
def closure = {State ->
it.toUpperCase()
}
//Varargs
def stringConcat = {String... it -> it.join('')}
stringConcat("abc","def","ghi")
def multiConcat = { int n, String... args ->
args.join('')*n
}
multiConcat(3,"John"," Carter ") |
Using Closures
Some of the useful methods applicable to Closures are listed below. See here for more information.
...
language | groovy |
---|
linenumbers | true |
---|
...
Include Page |
---|
| JMWE:Closures |
---|
| JMWE:Closures |
---|
|