John
John

Reputation: 145

How do you override a method for a java type instance with Groovy meta programming?

I am trying to override the functionality of a method of a java type instance in my Groovy code but I am getting a classcast exception.

I looked at the guide posted here but I can not get it to work.

Since my actual problem is a bit of mess, below is some runnable example code that fails with the same error. In the example I want to override the substring method of an instance of the java.lang.String class. In reality I want to override a method of an instance of a class that does not have a corresponding Groovy implementation, so the answer to my example is not to simply use a Groovy string instance.

class example {
    static void main(args) {
        java.lang.String hey = new java.lang.String("hey")
        ExpandoMetaClass emc = new ExpandoMetaClass( java.lang.String, false )
            emc.substring = {
                       "This is not a very good substring implementation"
                }
            emc.initialize()

        def proxiedHey = new groovy.util.Proxy().wrap(hey)
        proxiedHey.setMetaClass(emc)
        printf proxiedHey.toString()
        printf proxiedHey.substring(1)
    }
}

The above example fails at line 12, i.e printf meh.toString(). The exception thrown is

Caught: java.lang.ClassCastException: groovy.util.Proxy cannot be cast to java.lang.CharSequence at example.main(test.groovy:12)

So, any ideas on what I am doing wrong or if there is another way to solve my problem of adding and/or overriding methods of a java type instance?

I am using Groovy version 1.7.4.

Upvotes: 1

Views: 2306

Answers (2)

Alexander Suraphel
Alexander Suraphel

Reputation: 10603

Have you looked at Pimp my Library Pattern which allows you to add using Groovy Categories. You might find it more convenient and easy to understand in your case.

@Category(String)
class StringSubstrCategory {      
    def substring( int n)   { 
        "This is not a very good substring implementation"
    }
}

use (StringSubstrCategory) {
    "hey".substring(1)
}

Upvotes: 0

ataylor
ataylor

Reputation: 66059

You are creating an ExpandoMetaClass for java.lang.String, but assigning it to a groovy.util.Proxy. Make a metaClass for groovy.util.Proxy instread, like so:

java.lang.String hey = new java.lang.String("hey")
def proxiedHey = new groovy.util.Proxy().wrap(hey)
ExpandoMetaClass emc = new ExpandoMetaClass( groovy.util.Proxy, false )
emc.substring = {
    "This is not a very good substring implementation"
}
emc.initialize()

proxiedHey.setMetaClass(emc)
printf proxiedHey.toString()
printf proxiedHey.substring(1)

Upvotes: 2

Related Questions