Groovy 在这里做啥?

Posted

技术标签:

【中文标题】Groovy 在这里做啥?【英文标题】:What is Groovy doing here?Groovy 在这里做什么? 【发布时间】:2012-03-20 11:43:45 【问题描述】:

我试图调试一些使用 mixins 的代码,并且我能够将我的问题简化为这个示例。我有一个通过 mixin 接收方法的父类和一个从父类继承的子类。如果我尝试替换子类实例上的方法,它会起作用除非,我要替换的方法在父类实例被替换之前被调用。如果它已被调用,那么我无法替换它

所以这段代码:

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

【问题讨论】:

我也可以在 Groovy 1.8.4 中重现这个。我闻起来像虫子;但我不太喜欢 Groovy 元编程,所以我不知道。 感谢您的说明,如果我最终提交错误,我一定会包括在内。 我会在 groovy 用户邮件列表上问这个问题,对我来说闻起来像一个错误...... 这可能与任何方法处理程序缓存有关吗? 【参考方案1】:

metaClass 在方法调用中被查看,mixin 有自己的处理程序。 两者都是延迟加载的,并且是静态的,如果您不调用方法,则不会发生静态延迟加载。 Mixins 优先于 metaClass 覆盖,这就是为什么如果您初始化 A,它会显示 foo 而不会获胜。 元是在它所应用的对象上定义的,以便为每个类解析它,您需要 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 元存储的任何信息。 所有这些都取自文档并自己摆弄控制台。你的问题很有趣,在我看来,它本身就值得一篇博文。文档的 Dynamic Groovy 页面已经提供了一些答案 groovy.codehaus.org/Per-Instance+MetaClass

以上是关于Groovy 在这里做啥?的主要内容,如果未能解决你的问题,请参考以下文章

Gradle必备--Groovy基础

groovy与java语法区别

Groovy:没有开箱即用的 stringToMap 吗?

02-Groovy-IntelliJ IDEA配置Groovy开发环境

复杂多变场景下的Groovy脚本引擎实战

如何将 Grails 服务注入 src/groovy 类