我试图调试一些使用mixins的代码,我能够将我的问题减少到这个例子。我有一个父类,它通过mixin和从父类继承的子类接收方法。如果我尝试替换子类的实例上的方法,它就会工作 UNLESS 我替换的方法在替换之前在父类的实例上被调用。如果它已被调用,那么我无法替换它
所以这段代码:
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()
将屈服:
FOO
FOO
但是如果你在第13行(评论中注释出来的那个评论出来的那个评论)中你会得到:
获胜
为什么会这样?我希望在Groovy的元类模型的上下文中有一些方法可行,但我不明白。
这是Groovy 1.8.6
答案 0 :(得分:3)
在方法调用中查看metaClass,mixins有自己的处理程序。 两者都是延迟加载和静态的,如果不调用方法,则不会发生静态延迟加载 Mixins优先于metaClass覆盖,这就是为什么它显示foo而不是在你初始化A.的情况下获胜 在它应用的对象上定义了一个元,为了按类需要解析它需要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,类方法优先于object Metoreore方法。
证明:
@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