2011-08-16 69 views
1

我有以下代码:Groovy的:动态地将属性添加到从内部类方法Groovy类

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(),常规并没有试图去propertyMissing而只是抛出一个

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

一些网上搜索表明,这是因为myClass.myProperty调用一个getter方法,其重定向到propertyMissing。

我猜测,在类方法中,groovy不通过getter方法获取变量,这就是为什么propertyMissing没有被调用?

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

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

+0

为什么groovy在执行'myClass.myMethod();时抛出一个错误;'当关键字'def'或任何数据类型关键字如'string'缺少时? –

+1

我相信只有在脚本中运行它时,您才可以设置变量而不需要定义或声明它。当你在脚本中运行它时,如果没有定义或声明,那么这个变量会被放到脚本的Binding中(当你在脚本中时,你可以用getBinding()调用来访问它)。但是,当您没有运行脚本时,并没有“绑定”,并且Groovy希望您使用def或使用数据类型来声明它。 – user872831

+1

http://groovy.codehaus.org/Scoping+and+the+Semantics+of+%22def%22 – user872831

回答

11

你可以让你的类extend ExpandoExpando 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可以看出,这款手卷版本的检查工作量少得多,我相信它少了;-)

+1

完美的作品,谢谢!实际上,我在使用getProperty之前......但忘记了我正在尝试设置(未获取)属性并未实现setProperty ...但您对Expando的使用方式甚至更好。 =]接受为答案 – user872831