Hi all, my name is Hubert A. Klein Ikkink. Not a very common name, right? To make things easier I just picked the first letters of my firstname and surname and came up with haki. So there you have it, now I am also known as Mr. Haki or mrhaki for short. You can read more blog postings at www.mrhaki.com. I am a passionate Groovy and Java developer based in Tilburg, The Netherlands. My goal is to write clean, elegant, user-centered and high quality software. You can find me on Google+ and Twitter. Hubert is a DZone MVB and is not an employee of DZone and has posted 151 posts at DZone. You can read more from them at their website. View Full User Profile

Groovy Goodness: Using Implicit call() Method

10.07.2012
| 2734 views |
  • submit to reddit

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)

 

 

 

 

Published at DZone with permission of Hubert Klein Ikkink, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)