Groovy: this.metaClass Versus instance.metaClass

后端 未结 1 1765
野趣味
野趣味 2020-12-19 04:08

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

class Person{
  def work(){
    println \"work()\"
  }         


        
相关标签:
1条回答
  • 2020-12-19 04:50
    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)
    
    0 讨论(0)
提交回复
热议问题