简体   繁体   English

Groovy:从 class 方法内部动态地将属性添加到 groovy 类

[英]Groovy: dynamically add properties to groovy classes from inside class methods

I have the following code:我有以下代码:

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();

At myClass.myProperty, Missing property myProperty was printed out to the console.在 myClass.myProperty, Missing property myProperty被打印到控制台。

But then in myClass.myMethod() , groovy makes no attempt to go to propertyMissing but instead just throws a但是然后在myClass.myMethod()中, groovy 没有尝试 go 到propertyMissing而是只是抛出一个

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

Some search online indicates that it is because myClass.myProperty calls a getter method, which redirects to propertyMissing.网上有的搜索表明是因为myClass.myProperty调用了getter方法,重定向到propertyMissing。

I am guessing that within class methods, groovy doesn't go through getter methods for variables and that's why propertyMissing is not getting called?我猜在 class 方法中, groovy 不会 go 通过变量的 getter 方法,这就是为什么 propertyMissing 没有被调用?

Is there a way to achieve what I want to do using the dynamic propertyMissing , or getProperty , or anything like that?有没有办法使用动态propertyMissinggetProperty或类似的东西来实现我想要做的事情?

PS I don't want to do def variable =... or String variable =... in myMethod. PS我不想在myMethod中做def variable =...String variable =... I am hoping that the syntax within myMethod will stay as variable =... , but adding anything outside of that method is acceptable.我希望myMethod中的语法将保持为variable =... ,但是在该方法之外添加任何内容都是可以接受的。

You can make your class extend Expando ( Expando is described here )您可以使您的 class extend Expando此处描述了 Expando

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

You can hand-roll a similar functionality by creating your own backing map for variables, and writing the get/setProperty methods yourself, ie:您可以通过为变量创建自己的支持 map 并自己编写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

Though as you can see from the source code for Expando , this hand-rolled version does a lot less checks and I'd trust it less;-)尽管您可以从Expando 的源代码中看到,这个手动版本的检查要少得多,而且我会少相信它;-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM