views:

215

answers:

2

I would like to "spoil" plus method in Groovy in the following way:

Integer.metaClass.plus {Integer n -> delegate + n + 1}
assert 2+2 == 5

I am getting StackOverflowException (which is not surprising).

Is there any way to use "original" plus method inside metaclass' closure?

+1  A: 

Use this to "spoil" plus method:

Integer.metaClass.plus {Integer n -> delegate - (-n) - (-1)}
assert 2+2 == 5

Not surprisingly, using '+' operator in overloading plus method will result in StackOverflow, it is required to use something other then '+' operator.

Other mechanism: Use XOR or some bit operator magic.

Regards, Peacefulfire

peacefulfire
It seems that Groovy 1.6 is clever enough to change the call delegate - (-n) to delegate + n and StackOverflowException is still thrown
Piotr Kochański
hmm.. My version is Groovy 1.6 and Java 1.5.0_15 I ran that in groovy console and it ran fine without throwing any StackOverflowExceptionI ran in groovyshell and it ran fine. How are you trying to run above script?
peacefulfire
Just saw the answer posted above by Ted. I think that is far better and general solution. +1 to Ted.
peacefulfire
+3  A: 

The groovy idiomatic way is to save a reference to the old method and invoke it inside the new one.

def oldPlus = Integer.metaClass.getMetaMethod("plus", [Integer] as Class[])

Integer.metaClass.plus = { Integer n ->
    return oldPlus.invoke(oldPlus.invoke(delegate, n), 1)        
}

assert 5 == 2 + 2

This isn't actually that well documented and I was planning on putting up a blog post about this exact topic either tonight or tomorrow :).

Ted Naleid