Groovy Goodness: Using Implicit call() Method
In Groovy we can invoke an implicit call()
method on a Groovy object. We can leave out the call
method name and just use ()
. We can use meta programming to add an implementation for the call()
method to a class. In the following example script we add an implementation for the call()
method with a single parameter to the String
class. The implementation returns the element found at the range specified by the argument when we invoke the method:
String.metaClass.call = { range ->
delegate[range]
}
def value = 'Groovy is Gr8'
assert value(0) == 'G'
assert value(10) == 'G'
assert value(4) == value[4]
assert value.call(1) == value(1)
assert value(0..5) == 'Groovy'
Inspired by the examples http://groovyconsole.appspot.com/view.groovy?id=21006 and http://groovyconsole.appspot.com/script/21005 we can also write our own class and implement the call()
method. This can for example be used in DSLs.
class StringConverter {
def value
def value(s) {
value = s
this
}
/** Convert characters in value property if cond is true */
def upper(cond) {
value = value.collect { cond(it) ? it.toUpperCase() : it }.join()
}
def call(callable) {
callable
}
}
def converter = new StringConverter()
converter.with {
value 'mrhaki' upper { it < 'm' }
// Equivalent to:
// value('mrhaki') upper { it < 'm' }
// or
// value('mrhaki').call(upper { it < 'm' })
// or
// value('mrhaki').call(upper({ it < 'm' }))
}
assert converter.value == 'mrHAKI'
converter.with {
value('jdriven') upper { it == 'j' || it == 'd' }
assert value == 'JDriven'
}
Code written with Groovy 2.0.4