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

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

问题描述

我在本书中遇到了groovy脚本代码。

  class Person {
def work(){
println work()
}
def sports = ['basketball','football','voleyball']
def methodMissing(String name,args){
if(name在运动中){
println将$ {name}注入Person类
Person实例= this
printlnthis.metaClass:\ t\ $ $ {this.metaClass}
printlninstance.metaClass:\ t $ {instance.metaClass}
assert this.metaClass == instance.metaClass
} else {
printlnno such method:

$ b $ new $ Person $
jack.football(

输出如下:

 将足球注入Person类
this.metaClass:groovy.lang.MetaClassImpl@245b4bdc [class Person]
instance.metaClass:org.codehaus.groovy.runtime.HandleMetaClass@245b4bdc [groovy.lang.MetaClassImpl@245b4bdc [class Person]]
Caught:断言失败:
//为简单起见,我没有粘贴详细的断言

所以我很困惑:


  1. 为什么this.metaClass不等于instance.metaClass?

  2. 更多,我不能使用this.metaClass注入新的方法; groovy告诉我this.metaClass没有这样的属性,我打算注入。

  3. 什么是org.codehaus.groovy.runtime.HandleMetaClass@245b4bdc [groovy.lang.MetaClassImpl@245b4bdc [班人]]是什么意思?我知道245b4bdc可能是对象指针。但为什么HandleMetaClass和MetaClassImpl具有相同的指针值245b4bdc?

目前,我发现@ 245b4bdc不是 strong> Object reference ,所以 HandleMetaClass @ 245b4bdc 不一定与 MetaClassImpl @ 245b4bdc 相同。我们可以使用Object.is()方法来判断它们是否相同(我这样做了,结果是 false

解决方案


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



    它涉及到字段的访问权限。




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

    • 里面,groovy只是直接访问该字段,getFieldName()不会被调用。在我们的示例中,当我使用 this 时,我处于里面;因此 this.metaClass 将直接访问 metaClass 。最后,getMetaClass()返回一个 HandleMetaClass 对象,而内部metaClass是一个 MetaClassImpl 对象。因此 this.metaClass!= instance.metaClass


  2. metaClass.say = { - > printlnsay}会抛出MissingPropertyException?




    • this.metaClass的类型是MetaClassImpl


    • MetaClassImpl是一个低级别的类,它支持用于注入的高级类(例如.HandleMetaClass)。这并不意味着开发人员直接使用,所以它不支持注入方式: xxxx.say = { - > printlnsay}




    • 代码示例(对于问题1) $ p $ class Person {
      def work(){
      printlnwork()
      }
      def sports = ['basketball','football ','voleyball']
      def methodMissing(String name,args){
      if(体育运动中的名字){
      Person instance = this

      printlnthis。 metaClass:\\\
      \t $ {this.metaClass}
      printlninstance.metaClass:\\\
      \ $ $ {instance.metaClass}
      //输出:false
      printlnthis.metaClass.is(instance.metaClass):\\\
      \t $ {this.metaClass.is(instance.metaClass)}

      //输出:true
      printlnthis.getMetaClass()。is(instance.getMetaClass()):\\\
      \t $ {this.getMetaClass()。is(instance.getMetaClass())}

      }其他{
      printlnno这样的方法:Person类中的$ {name}()类

      }
      }
      def jack = new Person()
      jack.football()
      jack.football()

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

        class Cat {} 
      def a = new groovy.lang.MetaClassImpl(Cat)
      try {
      a。 say = { - > printlnsay}
      } catch(MissingPropertyException e){
      println[Fail] \\\
      \tcan not the method say()into MetaClassImpl class.\\\



      def b = new org.codehaus.groovy.runtime.HandleMetaClass(a)
      println b
      b.say = { - > println [say]}
      println[确定] \\\
      \tcan将方法say()放入HandleMetaClass类中\
      def method = b.getMetaMethod(say)
      method.invoke(this)


      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:\t\t${this.metaClass}"
              println "instance.metaClass:\t${instance.metaClass}"
              assert this.metaClass==instance.metaClass
          }else{
              println "no such method:${name}() in Person class"
          }
        }
      }
      def jack=new Person()
      jack.football()
      

      it's output is as below:

      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
      

      So I am quite confused:

      1. why is this.metaClass not equal to instance.metaClass?
      2. further more, I can not use this.metaClass to inject new methods; groovy tells me this.metaClass have no such property, which I intended to inject.
      3. What does "org.codehaus.groovy.runtime.HandleMetaClass@245b4bdc[groovy.lang.MetaClassImpl@245b4bdc[class Person]]" mean? I know "245b4bdc" may be the object pointer. But why HandleMetaClass and MetaClassImpl have the same pointer value "245b4bdc"?

      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. why this.metaClass != instance.metaClass?

        It involves groove's access to fields.

        • 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().

        • 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.

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

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

        • this.metaClass's type is MetaClassImpl

        • 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"}.

      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:\n\t${this.metaClass}"
              println "instance.metaClass:\n\t${instance.metaClass}"
              //output: false
              println "this.metaClass.is(instance.metaClass):\n\t${this.metaClass.is(instance.metaClass)}"
      
              //output: true
              println "this.getMetaClass().is(instance.getMetaClass()):\n\t${this.getMetaClass().is(instance.getMetaClass())}"
      
          }else{
              println "no such method:${name}() in Person class"
          }
        }
      }
      def jack=new Person()
      jack.football()
      jack.football()
      

      Code Sample(For Question 2):

      class Cat{}
          def a=new groovy.lang.MetaClassImpl(Cat)
      try{
          a.say={->println "say"}
      }catch(MissingPropertyException e){
          println "[Fail]\n\tcan not inject method say() into MetaClassImpl class.\n"
      }
      
      def b=new org.codehaus.groovy.runtime.HandleMetaClass(a)
      println b
      b.say={->println "[say]"}
      println "[OK]\n\tcan inject method say() into HandleMetaClass class\n"
      def method=b.getMetaMethod("say")
      method.invoke(this)
      

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

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