因此,将一个方法添加到接口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
这是预期的行为吗?如果是这样,为什么呢?或者这是一个错误?
最佳答案 哇,我认为这可能是一个长期存在的,未解决的错误( 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