Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change behaviour of the method in groovy using that method in metaclass

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?

like image 492
Piotr Kochański Avatar asked May 28 '09 12:05

Piotr Kochański


People also ask

How to define methods inside a Groovy script?

In Groovy, it is possible to define methods inside a script (without being inside a class). The generated class has all user defined methods. The code outside of the methods is copied into the run method. Let's compile above file with groovyc and analyze the compiled class with javap.

How to test a groovy class with a static method?

The below Account Groovy class has a static method called getType (). The Customer Groovy class you're trying to test calls the getType () static method within it's getAccountType () method:

What is metaclass in Groovy?

A MetaClass within Groovy defines the behaviour of any given Groovy or Java class. The MetaClass interface defines two parts. The client API, which is defined via the extend MetaObjectProtocol interface and the contract with the Groovy runtime system.

What is the output of the main function in Groovy?

In our main function we are actually creating an instance of the Example class and then invoking the method of the ‘ex’ object. The output of the above method would be the value 100. Groovy provides the facility just like java to have local and global parameters.


2 Answers

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 :).

like image 121
Ted Naleid Avatar answered Oct 17 '22 06:10

Ted Naleid


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

like image 1
Kartik Shah Avatar answered Oct 17 '22 06:10

Kartik Shah