因此,将一个方法添加到接口metaClass会将其添加到每个接口实现的实例中 - 但只能添加一次。将方法添加到每个实现类中,每次都可以进行更改。
在重新分配方法之前清理metaClass似乎没有任何改变。
这是一个可运行的例子:
interface X {}
class A implements X {}
class B implements X {}
X.metaClass.test = { println "v1" }
new A().test()
new B().test()
X.metaClass.test = { println "v2" }
new A().test()
new B().test()
A.metaClass.test = { println "v3" }
B.metaClass.test = { println "v3" }
new A().test()
new B().test()
A.metaClass.test = { println "v4" }
B.metaClass.test = { println "v4" }
new A().test()
new B().test()
结果是:
v1
v1
v1
v1
v3
v3
v4
v4
这是预期的行为吗?如果是这样,为什么呢?或者这是一个错误?
答案 0 :(得分:2)
哇,我认为这实际上可能是一个长期未解决的错误(GROOVY-3493)。看起来问题是,一旦在接口中声明了一个方法,就不能通过metaClass覆盖它。此限制不适用于类。
所以我的猜测是你第一次通过metaClass声明方法,它被正确初始化,因为它以前不存在。但是对接口metaClass方法的任何后续更新都不起作用,因为它已经存在。类metaClass更改有效,因为此错误不适用于它们。
故障单中列出的解决方法与您找到的解决方法类似;即,更新接口和类的metaClass:
interface X {}
class A implements X {}
class B implements X {}
X.metaClass.test = { println "v1" }
new A().test()
new B().test()
X.metaClass.test = { println "v2" }
A.metaClass.test = { println "v2" }
new A().test() // Will print "v2"
new B().test() // Will print "v1" still