开发者

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

开发者 https://www.devze.com 2023-03-28 16:12 出处:网络
I have the following code: class MyClass { def myMethod() { variable = \"I am a variable\" } def propertyMissing(String name) {

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.

But then in myClass.myMethod(), groovy makes no attempt to go to propertyMissing but instead just throws a

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.

I am guessing that within class methods, groovy doesn't go thr开发者_StackOverflowough getter methods for variables and that's why propertyMissing is not getting called?

Is there a way to achieve what I want to do using the dynamic propertyMissing, or getProperty, or anything like that?

P.S. I don't want to do def variable = ... or String variable = ... in myMethod. I am hoping that the syntax within myMethod will stay as variable = ..., but adding anything outside of that method is acceptable.


You can make your class 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

You can hand-roll a similar functionality by creating your own backing map for variables, and writing the get/setProperty methods yourself, ie:

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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号