Groovy在这里做什么?
问题描述:
我试图调试一些使用mixin的代码,我能够将我的问题简化为这个例子。我有一个父类,它通过一个mixin和一个从父类继承的子类来接收方法。如果我尝试替换子类的实例上的方法,它将起作用除非我更换的方法在父类的实例被替换之前调用。如果已被称为然后,我不能没有它Groovy在这里做什么?
所以这个代码:
class M {
protected foo() { println 'foo' }
}
@Mixin(M) class A {
def bar() { foo() }
}
class B extends A {}
def b = new B()
def a = new A()
a.bar() //<-- comment out this line and see the difference
b.metaClass.foo = {println 'winning'}
b.bar()
将产生:
富
富
但如果你注释掉第13行(带有评论的评论),你会得到:
获奖
为什么会出现这种情况?我期望在Groovy的元类模型的背景下有一些合理的方法,但我不明白。
这是Groovy的1.8.6
答
元类上的方法调用,并混入有自己的处理程序时看。 两者都是延迟加载的,而静态的,如果你不调用一个方法,静态延迟加载不会发生。
Mixins优先于metaClass覆盖,这就是为什么它显示foo并且如果初始化A而不会获胜。
meta定义在它所应用的对象上,以便按需要解析它。Object.class .metaClass(即这里B.metaClass)。 有趣的是这产生了:
groovy.lang.MissingMethodException: No signature of method: B.foo() is applicable for argument types:() values: []
Possible solutions: foo(), foo(java.lang.Object), bar(), any(), use([Ljava.lang.Object;), find(groovy.lang.Closure)
第B定义FOO解决错误:
class B extends A {
def foo() { println 'not winning' }
}
你的答案是的Mixin影响类metastore,和类方法优先对象metastore方法。
证明:
@Mixin(M)
class B extends A {
}
a.bar() //<-- comment out this line and see the difference
B.metaClass.foo = {println 'class winning'}
b.metaClass.foo = {println 'object winning'}
b.bar()
产量:
foo
class winning
一种不同的方法
class M {
protected foo() { println 'foo' }
}
@Mixin(M) class A {
def bar() { foo() }
}
class B extends A {
def bar() { foo() }
}
class C extends B {
def foo() { println 'wat' }
}
@Mixin(M)
class D extends C { }
def b = new B()
def a = new A()
def c = new C()
def d = new D()
a.bar() //<-- comment out this line and see the difference
b.metaClass.foo = {println 'winning'}
b.bar()
c.metaClass.foo = {println 'losing'}
c.bar()
d.metaClass.foo = {println 'draw'}
d.bar()
息率
foo
winning
wat
wat
我也可以在Groovy 1.8.4中重现这一点。闻起来像一个臭虫给我;但我并不太在意Groovy元编程,所以我不知道。 – epidemian 2012-03-01 22:55:08
感谢您的注意事项,如果我最终提出了一个错误,我一定会加入。 – mfollett 2012-03-01 23:27:00
我在groovy用户邮件列表上问这个,闻起来像是一个bug ... – 2012-03-01 23:47:35