Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add method to metaclass

I'm just playing with the metaclass programming in Groovy. But suddenly I was facing a little problem which I just could not get working...

Here is the simple script:

// define simple closure
def printValueClosure = {
 println "The value is: '$delegate'"
}

String.metaClass.printValueClosure = printValueClosure

// works fine
'variable A'.printValueClosure()



// define as method
def printValueMethod(String s){
 println "The value is: '$s'"
}

// how to do this!?
String.metaClass.printValueMethod = this.&printValueMethod(delegate)

'variable B'.printValueMethod()

Is it possible to use the method but set the first parameter to the calling object? using delegate seems not to work... The assignment of methods which do not reference the caller is no problem. Does currying work here?

Thanks, Ingo

like image 629
Leikingo Avatar asked Dec 10 '10 17:12

Leikingo


1 Answers

The simplest way to accomplish this is to wrap the method in a closure, like so:

def printValueMethod(String s){
    println "The value is: '$s'"
}

String.metaClass.printValueMethod = { -> printValueMethod(delegate) }

assert 'variable B'.printValueMethod() == "The value is: 'variable B'"

The idomatic way to add a method without using closures would be to create a category class and mix it in like so:

class PrintValueMethodCategory {
    static def printValueMethod(String s) {
        println "The value is: '$s'"
    }
}

String.metaClass.mixin(PrintValueMethodCategory)

assert 'variable B'.printValueMethod() == "The value is: 'variable B'"

I don't think currying can help in this particular case, since you don't know the value of the delegate at the time of assignment to the metaclass.

like image 72
ataylor Avatar answered Dec 04 '22 05:12

ataylor