如何在Groovy中动态地向闭包添加属性



我的环境是Groovy版本:2.5.1 JVM:1.8.0_151

正如您所知,您可以动态地将属性或方法添加到类中,如下所示:

class Cat {
}
def cat = new Cat()
cat.metaClass.name = "Amy"
cat.metaClass.greet = { println "Hello"}
println cat.name
cat.greet()

它运行正常。但当涉及到这样的关闭时:

def cat = {}
cat.metaClass.name = "Amy"
cat.metaClass.greet = { println "Hello"}
println cat.name
cat.greet()

它给出的错误如下:

捕获:groovy.lang.MissingPropertyException:没有这样的属性:类的名称:org.codehaus.groovy.runtime.metaclass.ClosureMetaClassgroovy.lang.MissingPropertyException:没有这样的属性:类的名称:org.codehaus.groovy.runtime.metaclass.ClosureMetaClass在test.run(test.groovy:7(

为什么?闭包也是Groovy中的一个对象。。。

Groovy为闭包使用了一种特殊形式的元类,称为"ClosureMetaClass",正如您的错误或以下片段所示:
def t = {}
def t2 = new Object()
println t.metaClass.class.simpleName // ClosureMetaClass
println t2.metaClass.class.simpleName // HandleMetaClass

这是因为在语言本身中,Groovy有一个特定的方法,它根据传递的Classtype返回一个MetaClass,并带有签名:

MetaClass getMetaClass(Class var1);

看看groovy的官方文档,ClosureMetaClass是"仅供内部使用"的。因此,您无法在运行时向其添加任何方法。

您可以将方法添加到闭包类本身的metaClass中。请参见此处。

删除metaClass

我在当地做了这个,效果很好。我自己还在学习groovy,所以我不知道它为什么有效。我想这是由于一个基本闭包没有metaClass信息。

def cat = {}
cat.name = "Amy"
cat.greet = { println "Hello"}
println cat.name
cat.greet()

最新更新