我在尝试在 Groovy 中使用属性访问时遇到了问题。参加以下课程:
class Foo {
Map m = [:]
String bar
void getProperty(String name) {
m.get name
}
def setProperty(String name, value) {
m.set name, value
}
String getBarString() {
return bar // local access, does not go through getProperty()
}
}
它覆盖了 getter 和 setter 以简单地将值放入 Map 而不是放入对象的普通属性空间。抽象地说,这有点傻,但是想象一下,我们没有将数据放入映射中,而是将其持久化到数据库或其他有用的东西中。
不幸的是,下面的代码现在不起作用:
foo = new Foo()
foo.bar = "blerg" // using foo.bar invokes the setProperty interceptor
assert foo.bar == "blerg" // this will work fine as foo.bar here uses the getProperty interceptor
assert foo.getBarString() == "blerg" // explosion and fire! getBarString accesses bar locally without going through the getProperty interceptor so null will actually be returned.
当然有解决方法,setProperty 可以同时设置 MetaProperty 和 Map 值等。但是,我想到的所有策略都需要程序员格外小心,以确保他们正在访问类中的属性他们的意思的确切方式。
此外,Groovy 中的一些内置很棒的东西(例如@Delegate)使用直接的 MetaProperty 访问而不是通过 getProperty,因此以下内容永远不会起作用:
class Meep {
String getMyMeep() {
return "MEEP!!!"
}
}
class Foo {
Map m = [:]
String bar
@Delegate Meep meep
void getProperty(String name) {
m.get name
}
def setProperty(String name, value) {
m.set name, value
}
String getBarString() {
return bar
}
}
foo = new Foo()
foo.meep = new Meep() // uses setProperty and so does not place the Meep in the Map m
foo.getMyMeep()
由于@Delegate 使用 MetaProperty 直接访问(实际上是 this.meep.getMyMeep() 而不是 getProperty 拦截器,因此在最后一行抛出空指针异常。不幸的是,'meep' 为空,但 getProperty('meep') 不会。
简而言之,我正在寻找一种解决以下标准的策略:
- 拦截属性读/写以启用自动替代数据存储
- 为其他开发人员提供透明或近乎透明的界面(我不想让其他人的生活变得更加艰难)
- 允许使用 MetaProperty/this/etc 对变量进行本地访问。访问方法
提前致谢!