groovy – 添加接口元类的方法只能工作一次

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