Groovy:this.metaClass 与 instance.metaClass [英] Groovy: this.metaClass Versus instance.metaClass

查看:18
本文介绍了Groovy:this.metaClass 与 instance.metaClass的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在书中遇到过下面的groovy脚本代码.它对我产生了一些奇怪的输出.

I have encountered below groovy script code in the book . And it generated some strange outputs to me.

class Person{
  def work(){
    println "work()"
  }
  def sports=['basketball','football','voleyball']
  def methodMissing(String name, args){
    if(name in sports){
        println "injected ${name} into Person class"
        Person instance=this
        println "this.metaClass:		${this.metaClass}"
        println "instance.metaClass:	${instance.metaClass}"
        assert this.metaClass==instance.metaClass
    }else{
        println "no such method:${name}() in Person class"
    }
  }
}
def jack=new Person()
jack.football()

输出如下:

injected football into Person class
this.metaClass:     groovy.lang.MetaClassImpl@245b4bdc[class Person]
instance.metaClass: org.codehaus.groovy.runtime.HandleMetaClass@245b4bdc[groovy.lang.MetaClassImpl@245b4bdc[class Person]]
Caught: Assertion failed: 
//I did not paste the detailed assertion here for simplicity

所以我很困惑:

  1. 为什么 this.metaClass 不等于 instance.metaClass?
  2. 此外,我不能使用 this.metaClass 来注入新方法;groovy 告诉我 this.metaClass 没有这样的属性,我打算注入.
  3. org.codehaus.groovy.runtime.HandleMetaClass@245b4bdc[groovy.lang.MetaClassImpl@245b4bdc[class Person]]"是什么意思?我知道245b4bdc"可能是对象指针.但是为什么 HandleMetaClass 和 MetaClassImpl 有相同的指针值245b4bdc"?

目前,我发现@245b4bdc 不是对象引用",所以 HandleMetaClass@245b4bdc 不一定与 MetaClassImpl@245b4bdc 是同一个实例.我们可以使用 Object.is() 方法来判断它们是否相同.(我这样做了,结果是false)

Currently, I figured out that @245b4bdc is not the "Object reference", So HandleMetaClass@245b4bdc is not necessarily the same instance as MetaClassImpl@245b4bdc. We can use Object.is() method to judge whether they are the same.(I did that, result is false)

推荐答案

  1. 为什么 this.metaClass != instance.metaClass?

  1. why this.metaClass != instance.metaClass?

它涉及到groove对字段的访问.

It involves groove's access to fields.

  • 当从外部"访问实例字段时,groovy 实际上调用了函数 getFieldName().在我的例子中,当我使用实例"时,我在外面;所以 instance.metaClass 会调用 instance.getMetaClass().

  • When accessing an instance field from "outside", groovy actually calls the function getFieldName(). In my example, when I use "instance", i am at the outside; So instance.metaClass will call instance.getMetaClass().

inside"访问实例字段时,groovy 只是直接访问该字段,不会调用 getFieldName().在我们的例子中,当我使用this"时,我在inside";所以this.metaClass"将直接访问metaClass".

When accessing an instance field from "inside", groovy simply directly access the field, getFieldName() is not called. In our example, when I use "this", i am at the "inside"; So "this.metaClass" will access "metaClass" directly.

最后,getMetaClass() 返回一个 HandleMetaClass 对象,而内部元类是一个 MetaClassImpl 对象.所以this.metaClass!=instance.metaClass.

Finally, getMetaClass() returns a HandleMetaClass object while the internal metaClass is a MetaClassImpl object. So this.metaClass!=instance.metaClass.

为什么 this.metaClass.say={->println "say"} 会抛出 MissingPropertyException?

Why this.metaClass.say={->println "say"} will throws MissingPropertyException?

  • this.metaClass 的类型是 MetaClassImpl

  • this.metaClass's type is MetaClassImpl

MetaClassImpl 是一个低级类,它支持用于注入的上级类(例如 HandleMetaClass).不适合Developer直接使用,所以不支持注入方式:xxxx.say={->println "say"}.

MetaClassImpl is a low level class, which supports upper level classes(eg. HandleMetaClass) for injection. It's not meant for Developer to use directly, So it does not support the injection way: xxxx.say={->println "say"}.

代码示例(针对问题 1):

Code Sample(For Question 1):

class Person{
  def work(){
    println "work()"
  }
  def sports=['basketball','football','voleyball']
  def methodMissing(String name, args){
    if(name in sports){
        Person instance=this

        println "this.metaClass:
	${this.metaClass}"
        println "instance.metaClass:
	${instance.metaClass}"
        //output: false
        println "this.metaClass.is(instance.metaClass):
	${this.metaClass.is(instance.metaClass)}"

        //output: true
        println "this.getMetaClass().is(instance.getMetaClass()):
	${this.getMetaClass().is(instance.getMetaClass())}"

    }else{
        println "no such method:${name}() in Person class"
    }
  }
}
def jack=new Person()
jack.football()
jack.football()

代码示例(对于问题 2):

Code Sample(For Question 2):

class Cat{}
    def a=new groovy.lang.MetaClassImpl(Cat)
try{
    a.say={->println "say"}
}catch(MissingPropertyException e){
    println "[Fail]
	can not inject method say() into MetaClassImpl class.
"
}

def b=new org.codehaus.groovy.runtime.HandleMetaClass(a)
println b
b.say={->println "[say]"}
println "[OK]
	can inject method say() into HandleMetaClass class
"
def method=b.getMetaMethod("say")
method.invoke(this)

这篇关于Groovy:this.metaClass 与 instance.metaClass的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆