我很难理解GroovyClassLoader缓存是如何与扩张性方法工作的。
特别是,我期望下面的代码为每次调用Number.test()提供不同的输出,但事实并非如此。
int i = 1
Number.metaClass.test = {
return "A string"
}
println i.test()
println GroovySystem.metaClassRegistry.getMetaClass(Number.class)
Number.metaClass = null
println GroovySystem.metaClassRegistry.getMetaClass(Number.class)
Number.metaClass.test = {
return "Another String"
}
println i.test()
println GroovySystem.metaClassRegistry.getMetaClass(Number.class)
GroovySystem.metaClassRegistry.removeMetaClass(Number.class)
println GroovySystem.metaClassRegistry.getMetaClass(Number.class)
Number.metaClass.test = {
return "Yet another String"
}
println i.test()
输出:
A string
groovy.lang.ExpandoMetaClass@3571b748[class java.lang.Number]
groovy.lang.MetaClassImpl@7748410a[class java.lang.Number]
A string
groovy.lang.ExpandoMetaClass@37f1104d[class java.lang.Number]
groovy.lang.MetaClassImpl@55740540[class java.lang.Number]
A string
编辑:
我尝试了更多的东西。看来我的系统表现得很奇怪。考虑到以下代码:
def i = 1
i.class
Number.metaClass.test = {
return "A string"
}
println i.test()
Number.metaClass = null
Number.metaClass.test = {
return "Another String"
}
println i.test()
GroovySystem.metaClassRegistry.removeMetaClass(Number.class)
Number.metaClass.test = {
return "Yet another String"
}
println i.test()
当我在我的系统上执行它时,它按预期的方式工作(在输出中得到3个不同的字符串),但是如果我评论被认为无用的A string
,它会失败(3x i.class
)。
但是,如果我在groovy-line e.apppot.com上执行它,它就会给出预期的输出,不管有没有这一行.
我有点不知所措。
发布于 2016-10-07 06:44:21
创建int i = 9
时,它使用当前的Number.metaClass
创建一个对象。它接受创建一个新方法(read Number.metaClass.test = { "A string" }
),但不允许重载已经存在的方法。您可以更改对象的元类:
int i = 1
Number.metaClass.test = { "A string" }
assert i.test() == "A string"
Number.metaClass = null
i.metaClass.test = { "Another String" }
assert i.test() == "Another String"
GroovySystem.metaClassRegistry.removeMetaClass(Number.class)
assert i.test() == "Another String"
i.metaClass.test = { "Yet another String" }
assert i.test() == "Yet another String"
在我看来,需要调用i.class
就像个窃听器.看看jira,我看到了一些未解决的和打开的bug。我觉得你的看起来和这些很像:
在Java类metaClass上重写方法直到实例metaClass更改后才生效:https://issues.apache.org/jira/browse/GROOVY-5065 使用metaClass覆盖类层次结构中的方法不像预期的那样工作:https://issues.apache.org/jira/browse/GROOVY-3942 通过.metaClass重写方法的行为不一致:https://issues.apache.org/jira/browse/GROOVY-6847 删除metaClass方法:https://issues.apache.org/jira/browse/GROOVY-4189
如果您考虑一个具体的类,那么我的答案的第一部分起作用:
class Echo {}
Echo.metaClass.test = { "A string" }
def i = new Echo()
assert i.test() == "A string"
Echo.metaClass = null
Echo.metaClass.test = { "Another String" }
assert i.test() == "A string"
i.metaClass.test = { "Another String" }
assert i.test() == "Another String"
i.metaClass.test = { "Yet another String" }
assert i.test() == "Yet another String"
https://stackoverflow.com/questions/39918834
复制