开发者

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 correspondi开发者_如何转开发ng 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.


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)


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)
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜