2011-07-04 82 views
5

使用Groovy 1.8。我試圖創建一個動態類定義,將緩存每個對象的屬性。我沒有使用propertyMissing而沒有將屬性添加到對象就好了。我只是認爲緩存這些屬性會更有效率。對?Groovy每個對象的動態屬性

請注意,每個實例必須具有其自己的不同屬性。

下面的代碼工作正常:

class C {} 
def c = new C() 
c.metaClass.prop = "a C property" 
println c.prop 

def x = new C() 
x.prop 

將輸出:

a C property 
groovy.lang.MissingPropertyException: No such property: prop for class: C 

如果我需要這有問題:

class A { 
    def propertyMissing(String name) { 
     if(!this.hasProperty(name)) { 
      println "create new propery $name" 
      this.metaClass."$name" = "Dyna prop $name" 
      println "created new propery $name" 
     } 
     this.metaClass."$name" 
    } 
} 

a = new A() 
println a.p1 

A,我走得越遠「創建新的財產「,但行this.metaClass."$name" = "Dyna prop $name"失敗:No such property: p1 for class at line 5

怎麼了?

回答

8

此代碼應該做你想要什麼:

class A { 
    A() { 
    def mc = new ExpandoMetaClass(A, false, true) 
    mc.initialize() 
    this.metaClass = mc 
    } 

    def propertyMissing(String name) { 
    println "create new propery $name" 
    def result = "Dyna prop $name" 
    this.metaClass."$name" = result 
    println "created new propery $name" 
    result 
    } 
} 

a = new A() 
println a.p1 
println a.p1 

輸出:

create new propery p1 
created new propery p1 
Dyna prop p1 
Dyna prop p1 
1

ExpandoMetaClass並非真的被設計用於初始化或實例變量之後(請參閱下面的參考資料,至少1.6或更高版本)。可能要使用Runtime mixins。更多信息herehere

您可能需要閱讀blogpost,該解決方案提供了一種解決方案,用於在運行時定義屬性。和相關的groovy bug(這不是一個真正的bug)有關。

我在評論區看到,並至少在1.6版ExpandoMetaClass文檔驗證:

默認方法只允許 初始化之前加入()是 調用。換句話說,你創建一個 新的ExpandoMetaClass,添加一些方法 ,然後調用initialize()。如果 嘗試在 之後嘗試添加新方法,則會調用initialize(),將會拋出錯誤 。

+0

啊哈..你只能在編譯時做這個..太糟糕了。 – Ayman

+0

您可以使用運行時mixin運行時 – Manny

+0

修復「blogpost」斷開的鏈接:http:// blog。enfranchisedmind.com/2008/06/groovy-metaclass-bug/ –

6

你爲什麼不存儲在一個簡單的HashMap動態特性?

class Foo { 
    def storage = [:] 
    def propertyMissing(String name, value) { storage[name] = value } 
    def propertyMissing(String name) { storage[name] } 
} 
def f = new Foo() 
f.foo = "bar" 

這是從標準的例子:http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing

注意,你不必檢查屬性真的錯過......如果不會缺少它,則該方法不會首先被稱爲。