每个对象的Groovy动态属性

时间:2011-07-04 07:15:26

标签: dynamic groovy properties metaprogramming

使用Groovy 1.8。我正在尝试创建一个动态类定义,它将缓存每个对象的属性。我确实使用了propertyMissing而没有将属性添加到对象中。我只是认为缓存属性会更有效率。正确?

请注意,每个实例必须具有自己的不同属性。

以下代码可以正常使用:

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

怎么了?

3 个答案:

答案 0 :(得分: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 :(得分: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

的标准示例

注意,您不必检查属性是否真的丢失......如果它不会丢失,则首先不会调用该方法。

答案 2 :(得分:1)

ExpandoMetaClass实际上并不是设计用于初始化或实例变量之后(请参阅下面的参考,至少为1.6或更早版本)。

也许你想使用Runtime mixins。更多信息herehere

您可能希望阅读blogpost,其中提供了一种解决方法,用于在运行时定义属性。与之相关的相关groovy bug(这不是真正的错误)。

我在评论部分看到并至少在版本1.6 ExpandoMetaClass文档中验证了:

  

默认情况下,只允许使用方法   在initialize()之前添加   调用。换句话说,你创建一个   新的ExpandoMetaClass,添加一些方法   然后调用initialize()。如果你   之后尝试添加新方法   initialize()被称为错误   将被抛出。