【发布时间】:2018-11-17 14:55:50
【问题描述】:
我想覆盖元类上的动态属性,但它没有像我预期的那样工作。这是一个演示问题的简单示例。你可以在Groovy web console在线运行它
class Bike {}
class Bell { def ring() { println("calling " + this) } }
def createNamespaces = {
return [ "bell": new Bell() ]
}
def resetNamespaces = { bike ->
// setting to null means 'set it to the default'
bike.metaClass = null
createNamespaces().each { name, namespace ->
println("setting " + namespace)
bike.metaClass."$name" = namespace
}
}
def bike= new Bike()
resetNamespaces(bike)
bike.bell.ring()
resetNamespaces(bike)
bike.bell.ring()
结果是:
setting Bell@14e9bd2b
calling Bell@14e9bd2b
setting Bell@948a7ad
calling Bell@14e9bd2b
因此,尽管我更改了元类的属性,但调用它总是返回设置的第一个对象。是否有某种缓存?
当我将示例的最后一部分更改为:
resetNamespaces(bike)
resetNamespaces(bike)
bike.bell.ring()
那么结果如预期。也就是说,调用该属性会返回最后在 metaClass 上设置的对象:
setting Bell@5b47e0c7
setting Bell@19f373a4
calling Bell@19f373a4
我什至尝试如下手动设置元类
def resetNamespaces = { bike ->
def newMetaClass = new ExpandoMetaClass(Bike.class, true, true)
newMetaClass.initialize()
bike.metaClass = newMetaClass
...
}
但结果还是一样。所以肯定有一些缓存机制。我在文档中找不到有关此行为的任何信息。
【问题讨论】: