Groovy-将属性或方法动态添加到此

Groovy-将属性或方法动态添加到此,groovy,Groovy,我想向当前对象的元类动态添加一个字段和方法。我试过了 this.metaClass.testProp = "test" 添加名为testProp的字段。然而,我明白了 groovy.lang.MissingPropertyException: No such property: testProp for class: groovy.lang.MetaClassImpl 当我在类级别执行相同操作时,例如,将testProp添加到类中,而不是直接添加到对象中 Process.metaClass.

我想向当前对象的
元类
动态添加一个字段和方法。我试过了

this.metaClass.testProp = "test"
添加名为
testProp
的字段。然而,我明白了

groovy.lang.MissingPropertyException: No such property: testProp for class: groovy.lang.MetaClassImpl
当我在类级别执行相同操作时,例如,将testProp添加到类中,而不是直接添加到对象中

Process.metaClass.testProp = "test"

它可以工作,但我的对象不会继承该字段。如果您有任何正确的想法或建议,我们将不胜感激。

简短回答:

Process.metaClass.testProp = "test"
this.metaClass = null
assert this.testProp == "test"
长答案:

Process.metaClass.testProp = "test"
this.metaClass = null
assert this.testProp == "test"
我想,有三件事让你在这里成为一个问题。第一个是有一个元数据类的全局注册表。第二个是Groovy允许每个实例的元类(这是Groovy类的默认值)。第三个是默认的元类不允许运行时元编程

因此,如果执行运行时元编程,则需要将默认值替换为ExpandoMetaClass(EMC),以实现这一点。但由于存在每个实例的元类逻辑,这种替换可能不会影响所有实例。实例的元类在第一次使用时从全局注册表中获取
Process.metaClass.testProp=“test”
更改全局保存的文件。任何已经有一个元类的实例都不知道更改,因此也不知道属性
this.metaClass.testProp=“test”
将仅更改当前实例的元类,其他实例可能不知道它。您可以使用
this.metaclass=null
重置它。它将再次从全局注册表请求元类。如果您进行了全局更改,您的更改现在可见

如果您使用Groovy中的默认元类(MetaClassImpl),所有这些都很重要。如果您在代码中做了类似的更改,那么新的元类将是ExpandoMetaClass(EMC)。这个元类允许更改,因此进一步的更改不会导致替换元类。为了确保所有实例从一开始就使用ExpandoMetaClass,您通常会有如下设置代码:
ExpandoMetaClass.enableGlobal()

为了解决你的问题,我可以这么做

Process.metaClass.testProp = "test"
this.metaClass = null
assert this.testProp == "test"
如果您以前在某些设置代码中使用了
ExpandoMetaClass.enableglobal()
,则可以不使用meta类的重置代码(或者如果全局meta类与“this”的重置代码相同,并且是EMC的重置代码)。例如,Grails使用EMC作为默认值