添加方法到接口元类只能工作一次

时间:2017-03-26 22:02:33

标签: groovy metaprogramming

因此,将一个方法添加到接口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

这是预期的行为吗?如果是这样,为什么呢?或者这是一个错误?

1 个答案:

答案 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