Я хотел бы перезаписать динамическое свойство в метаклассе, но оно не работает так, как я ожидал.Вот простой пример, который демонстрирует проблему.Вы можете запустить его в режиме онлайн на Groovy веб-консоли
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()
Тогда результат будет таким, как ожидалось.То есть, вызов свойства возвращает объект, который был установлен в метаклассе как последний:
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
...
}
Но результатвсе тот же.Так что должен быть какой-то механизм кеширования.Я не могу найти ничего об этом поведении в документации.