【问题标题】:Groovy: dynamically add properties to groovy classes from inside class methodsGroovy:从类方法内部动态地将属性添加到 groovy 类
【发布时间】:2011-08-16 13:22:13
【问题描述】:

我有以下代码:

class MyClass {
    def myMethod() {
        variable = "I am a variable"
    }

    def propertyMissing(String name) {
        println "Missing property $name"
    }
}

MyClass myClass = new MyClass();
myClass.myProperty
myClass.myMethod();

在 myClass.myProperty,Missing property myProperty 被打印到控制台。

但是在myClass.myMethod() 中,groovy 并没有尝试去propertyMissing,而是抛出一个

groovy.lang.MissingPropertyException: No such property: variable for class: MyClass

网上有搜索显示是因为myClass.myProperty调用了getter方法,重定向到propertyMissing。

我猜想在类方法中,groovy 不会通过 getter 方法获取变量,这就是为什么不会调用 propertyMissing 的原因?

有没有办法使用动态propertyMissinggetProperty 或类似的东西来实现我想要做的事情?

附:我不想在 myMethod 中执行 def variable = ...String variable = ...。我希望myMethod 中的语法将保持为variable = ...,但在该方法之外添加任何内容都是可以接受的。

【问题讨论】:

  • 当关键字def 或任何数据类型关键字(如string)丢失时,为什么groovy 在执行myClass.myMethod(); 时会抛出错误?
  • 我相信当你在脚本中运行它时,你只能设置变量而不定义或声明。当您在脚本中运行它而不定义或声明时,该变量将被放入脚本的绑定中(您可以在脚本中使用 getBinding() 调用访问该绑定)。但是,当您不运行脚本时,没有“绑定”,Groovy 期望您使用 def 或使用数据类型声明它。

标签: groovy properties


【解决方案1】:

你可以让你的班级extend Expando (Expando is described here)

class MyClass extends Expando {
    def myMethod() {
        variable = "I am a variable"
    }

    def propertyMissing(String name) {
        println "Missing property $name"
    }
}

MyClass myClass = new MyClass()
myClass.myProperty
myClass.myMethod()
println myClass.variable

您可以通过为变量创建自己的支持映射并自己编写 get/setProperty 方法来手动实现类似的功能,即:

class MyClass {

    def myMethod() {
        variable = "I am a variable"
    }

    def propertyMissing(String name) {
        println "Missing property $name"
    }

    def backingMap = [:]

    Object getProperty( String property ) {
      if( backingMap[ property ] == null ) {
        propertyMissing( property )
      }
      else {
        backingMap[ property ]
      }
    }

    void setProperty( String property, Object value ) {
      backingMap[ property ] = value
    }
}

MyClass myClass = new MyClass()
myClass.myProperty
myClass.myMethod()
println myClass.variable

尽管您可以从 source code for Expando 中看到,这个手卷版本的检查要少得多,我会少信任它;-)

【讨论】:

  • 完美运行,谢谢!实际上,我之前曾使用过 getProperty...但忘记了我正在尝试设置(而不是获取)属性并且没有实现 setProperty...但是您使用 Expando 的方式更好。 =] 接受为答案
猜你喜欢
  • 2013-02-12
  • 2013-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多