Метакласс просматривается при вызове метода, а миксины имеют свой собственный обработчик.Оба загружаются лениво и статично, если вы не вызываете метод, статическая ленивая загрузка не происходит.
Миксины имеют приоритет над переопределениями метакласса, поэтому он отображает foo и не выигрывает, если вы инициализируете A.
Ameta определяется на объекте, к которому он применяется, для его разрешения для каждого класса вам необходим 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)
Определение foo на B устраняет ошибку:
class B extends A {
def foo() { println 'not winning' }
}
Ваш ответ заключается в том, что Mixin влияет на метасторое класс, а методы класса имеют приоритет над методами метастазов объекта,
Доказательство:
@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