Groovy:从类内方法向Groovy类动态添加属性

Groovy:从类内方法向Groovy类动态添加属性,groovy,properties,Groovy,Properties,我有以下代码: 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();

我有以下代码:

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中,
缺少的属性myProperty
被打印到控制台

但是在
myClass.myMethod()
中,groovy没有尝试转到
属性missing
,而是抛出一个

groovy.lang.MissingPropertyException: No such property: variable for class: MyClass
一些在线搜索表明这是因为
myClass.myProperty
调用了一个getter方法,该方法重定向到propertyMissing

我猜在类方法中,groovy没有对变量使用getter方法,这就是为什么没有调用propertyMissing

有没有一种方法可以通过使用动态
属性missing
,或
getProperty
,或诸如此类的工具来实现我想要做的事情


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

您可以让类
扩展Expando
()

通过为变量创建自己的支持映射,并自己编写
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

虽然正如您从中看到的,这个手动版本执行的检查要少得多,而且我不太相信它;-)

很好用,谢谢!事实上,我以前在使用getProperty。。。但是我忘记了我正在尝试设置(不获取)属性,并且没有实现setProperty。。。但您使用Expando的方式更好。=]被接受为groovy为什么执行
myClass.myMethod()时抛出错误的答案
当关键字
def
或任何数据类型关键字(如
string
)丢失时?我相信在脚本中运行变量时,您只能设置变量,而无需定义或声明。如果在脚本中运行该变量而不进行定义或声明,那么该变量将被放入脚本的绑定(在脚本中时,可以通过getBinding()调用访问该绑定)。但是,当您不运行脚本时,就没有“绑定”,Groovy希望您使用def或使用数据类型声明它。
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