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)