Groovy在这做什么?

时间:2012-03-01 22:42:48

标签: inheritance groovy mixins metaclass

我试图调试一些使用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

1 个答案:

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