首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >覆盖已通过expandoMetaClass添加的方法

覆盖已通过expandoMetaClass添加的方法
EN

Stack Overflow用户
提问于 2016-10-07 13:47:14
回答 1查看 68关注 0票数 0

我很难理解GroovyClassLoader缓存是如何与扩张性方法工作的。

特别是,我期望下面的代码为每次调用Number.test()提供不同的输出,但事实并非如此。

代码语言:javascript
代码运行次数:0
运行
复制
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()

输出:

代码语言:javascript
代码运行次数:0
运行
复制
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

编辑:

我尝试了更多的东西。看来我的系统表现得很奇怪。考虑到以下代码:

代码语言:javascript
代码运行次数:0
运行
复制
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上执行它,它就会给出预期的输出,不管有没有这一行.

我有点不知所措。

EN

回答 1

Stack Overflow用户

发布于 2016-10-07 14:44:21

创建int i = 9时,它使用当前的Number.metaClass创建一个对象。它接受创建一个新方法(read Number.metaClass.test = { "A string" }),但不允许重载已经存在的方法。您可以更改对象的元类:

代码语言:javascript
代码运行次数:0
运行
复制
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

如果您考虑一个具体的类,那么我的答案的第一部分起作用:

代码语言:javascript
代码运行次数:0
运行
复制
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"
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39918834

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档