如果这是一个小问题,请向所有Groovy爱好者道歉。
在SOAPUI中,我可以创建一个Groovy脚本,在其中我可以为运行上下文定义一个任意变量,以便以后检索。
context.previouslyUndefinedVariable = 3
def num = context.previouslyUndefinedVariable
Groovy的什么功能允许将以前未定义的变量添加到这样的对象中?我想了解更多关于它的信息。
非常感谢!
要了解更多信息,请参阅:
- Groovy的MetaClass用于什么
- Groovy的优点:使用ExpandoMetaClass向类动态添加方法
- 运行时和编译时元编程
公认的答案对SoapUI是如何做到这一点的解释有点糟糕。
在这种情况下,context
总是某个SoapUI库java类(如WsdlTestRunContext
(的实例,这些都是Map
的实现。您可以检查context.getClass()
和assert context in Map
。
在Map上查找属性时,Groovy使用getAt和putAt方法。你可以使用各种语法。所有这些都是等价的:
context.someUndef
context.'someUndef'
context[someUndef]
context['someUndef']
context.getAt('someUndef')
和
context.someUndef = 3
context.'someUndef' = 3
context[someUndef] = 3
context['someUndef'] = 3
context.putAt('someUndef', 3)
我喜欢使用上面任何一个包含引号的属性,这样GroovyEclipse就不会将其标记为缺少的属性。
同样有趣的是,Groovy在检查被称为属性的get
方法之前会先查找getAt()
方法。
例如,考虑评估"foo".class
。String实例没有一个名为class
的属性,也没有一个方法getAt(String)
,所以它接下来尝试的是寻找一个同名的"get"方法,即getClass()
,它找到了它,我们得到了结果:String
。
但对于映射,['class':'bar'].class
首先引用调用getAt('class')
的方法,即'bar'
。如果我们想知道它是什么类型的Map,我们必须更具体地写完整的:['class':'bar'].getClass()
,也就是LinkedHashMap
。
即使Map
没有匹配的密钥,我们仍然必须指定getClass()
,因为['foo':'bar'].class
仍然意味着['foo':'bar'].getAt('class')
,也就是null
。