如何使用Groovy元编程覆盖java类型实例的方法?

时间:2010-10-27 17:09:11

标签: groovy metaprogramming

我试图在我的Groovy代码中覆盖java类型实例的方法的功能,但我得到一个classcast异常。

我查看了here发布的指南,但我无法让它发挥作用。

由于我的实际问题有点混乱,下面是一些可运行的示例代码,它们失败并出现相同的错误。 在示例中,我想覆盖java.lang.String类的实例的substring方法。实际上我想覆盖一个没有相应Groovy实现的类实例的方法,所以我的例子的答案不是简单地使用Groovy字符串实例。

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

上面的例子在第12行失败,即printf meh.toString()。引发的异常是

  

抓住:java.lang.ClassCastException:   groovy.util.Proxy无法强制转换为   java.lang.CharSequence at   example.main(test.groovy:12)

那么,关于我做错了什么或者是否有另一种方法来解决我添加和/或覆盖java类型实例的方法的问题的任何想法?

我使用的是Groovy 1.7.4版。

2 个答案:

答案 0 :(得分:2)

您正在为java.lang.String创建ExpandoMetaClass,但将其分配给groovy.util.Proxy。为groovy.util.Proxy instread创建一个metaClass,如下所示:

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)

答案 1 :(得分:0)

您是否查看过允许使用Pimp my Library Pattern添加的Groovy Categories。在您的情况下,您可能会发现它更方便,更容易理解。

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

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