Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Groovy 将方法添加到接口元类只能工作一次_Groovy_Metaprogramming - Fatal编程技术网

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

Groovy 将方法添加到接口元类只能工作一次,groovy,metaprogramming,Groovy,Metaprogramming,因此,将方法添加到接口元类会将其添加到接口实现的每个实例中,但只添加一次。每次将该方法添加到每个实现类都会起作用,这是一个变化 在重新分配方法之间清理元类似乎不会改变任何东西 以下是一个可运行的示例: interface X {} class A implements X {} class B implements X {} X.metaClass.test = { println "v1" } new A().test() new B().test() X.metaClass.test =

因此,将方法添加到接口元类会将其添加到接口实现的每个实例中,但只添加一次。每次将该方法添加到每个实现类都会起作用,这是一个变化

在重新分配方法之间清理元类似乎不会改变任何东西

以下是一个可运行的示例:

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

这是故意的行为吗?如果是,为什么?还是一个bug?

哇,我认为这实际上可能是一个长期未解决的bug()。问题似乎在于,一旦在接口中声明了方法,就不能通过元类重写它。此限制不适用于类

因此,我猜是您第一次通过元类声明该方法时,它被正确初始化,因为它以前不存在。但是对接口元类方法的任何后续更新都不起作用,因为它已经存在。由于这个bug不适用于类元类,所以类元类的更改是有效的

记录单中列出的解决方法似乎与您找到的类似;即,更新接口和类上的元类:


您是否期待
v2
?在接口中,如何声明相同的方法?一旦正确?输出是预期的;您的期望是什么?没错,我希望在
X
接口上重写
test
方法会调用它来使用重写的行为,即打印“v2”字符串。对不起,我不太明白你反问句的明显性。当我做类似于元类.someMethod的事情时,我希望我不是真的两次声明同一个方法,而是重写前面的声明。有没有其他方法可以做到这一点?另外,如果将“metaClass.someMethod”解释为“两次声明相同的方法”,而不是重写以前的实现(在目标类上执行相同的操作时似乎会解释),我希望会出现某种异常。哇,感谢找到错误,我也在寻找,但失败了。长时间语言特性中的bug并不是一个理智的开发人员所期望的,所以知道它确实是这样是很好的,而不是我对它应该如何工作缺乏理解。然后。。。8年,很好!这一个比提供的门更老练,仍然没有解决!我会把赏金再留几天,也许它会引起更多的关注。
​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