在 Groovy 的 NodeChild 上添加动态方法的奇怪行为

Strange behaviour of adding dynamic methods on Groovy's NodeChild

我正在使用 Grails XML Parser 来解析 XML 字符串,在获得解析的 NodeChild 实例后,我在该实例上添加动态方法,如下所示:

import grails.converters.XML
import groovy.util.slurpersupport.NodeChild

NodeChild result = XML.parse("<root></root>")

result.getMetaClass().methodA = { return "a" }
result.getMetaClass().methodB = { return "b" }

println rootNode.methodA()
println rootNode.methodB()

现在我调用 methodA() 并期望打印 "a" 的行,我得到 MissingMethodException 找不到 methodA()

我对此进行了一段时间的调查,发现所有动态方法都被我们添加的最后一个动态方法所取代,即在这种情况下:methodB() 正在取代(或做某事)methodA(),所以我先调用 & print methodB(),它会正确打印 "b"。

这让我想到另一个测试如下:

import grails.converters.XML
import groovy.util.slurpersupport.NodeChild

String result = "any-other-data-type-instance-here-to-inject-dynamic-methods"

result.getMetaClass().methodA = { return "a" }
result.getMetaClass().methodB = { return "b" }

println rootNode.methodA()
println rootNode.methodB()

在这种情况下,两条语句都可以正常打印。所以问题只出在类NodeChild上。我使用 exando 元类功能很长时间了,我遇到了这样的问题。知道为什么会这样吗?

您需要在返回实例之前分配 metaclass 方法,否则它将具有旧的 metaclass 而不是具有新方法的新方法。此外,分配给 class,而不是实例 - 我不确定您是否只想影响此实例的元 class,但这不是语法。

这个有效:

import grails.converters.XML
import groovy.util.slurpersupport.NodeChild

NodeChild.metaClass.methodA = { return "a" }
NodeChild.metaClass.methodB = { return "b" }

NodeChild result = XML.parse("<root></root>")

println result.methodA()
println result.methodB()

请注意,您使用隐式 it 参数定义方法,但不传递任何内容,因此 Groovy 传递空值。如果您打算让方法没有参数,请使用此语法:

NodeChild.metaClass.methodA = { -> return "a" }
NodeChild.metaClass.methodB = { -> return "b" }