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()
}
}
ゲッターとセッターをオーバーライドして、オブジェクトの通常のプロパティスペースではなく、マップに値を配置します。要約すると、これは少しばかげていますが、データをマップに配置する代わりに、DBまたは他の便利なものに永続化していたと想像してください。
残念ながら、次のコードは機能しなくなりました。
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など)は、getPropertyを経由するのではなく、直接MetaPropertyアクセスを使用するため、以下は機能しません。
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はgetPropertyインターセプターではなくMetaProperty直接アクセス(事実上this.meep.getMyMeep())を使用するため、最後の行でnullポインター例外がスローされます。残念ながら'meep'はnullですが、getProperty('meep')はnullではありません。
要するに、私が探しているのは、次の基準を解決するための戦略です。
- プロパティの読み取り/書き込みをインターセプトして、自動代替データストレージを有効にします
- 他の開発者のための透明またはほぼ透明なインターフェース(私は他の人々の生活を著しく困難にしたくありません)
- MetaProperty / this/etcを使用して変数のローカルアクセスを許可します。アクセス方法
前もって感謝します!