Groovy instance.metaclass vs this.metaclass

风流意气都作罢 提交于 2019-12-01 11:35:15

问题


I have a following script:

task myTask {}

class Person {

     Person() {
        Person instance = this
        println this.metaClass.class.name
        println this.getMetaClass().class.name
        println instance.metaClass.class.name
        println instance.getMetaClass().class.name
    }
}

Person person = new Person()

And the output is :

groovy.lang.MetaClassImpl
groovy.lang.MetaClassImpl
org.codehaus.groovy.runtime.HandleMetaClass
org.codehaus.groovy.runtime.HandleMetaClass

Can anyone explain to me what is going on?

Thanks in advance.


回答1:


Take a look at this class,

class Person {

    def a, b

    Person() {
        a = this
        b = this
        println "this $this"
        println "a $a"
        println "b $b"
    }

    def printAll() {
        println "this.metaClass ${this.metaClass}"
        println "this.class.metaClass ${this.class.metaClass}"
        println "a.metaClass ${a.metaClass}"
        println "b.metaClass ${b.metaClass}"
    }
}

Take a look at the screenshot of the groovysh. It might give you a little hint about what's going on.

  1. p and q are two different objects, but
  2. p.metaClass is the same as q.metaClass, and
  3. printAll prints exactly the same thing for both, p and q
  4. a.metaClass and b.metaClass are holding this.class.metaClass, not this.metaClass, you see

There is only one object created of MetaClassImpl, and also only one of HandleMetaClass, for Person. And no matter how many times you instantiate Person, they will be assigned to the instance. But, when you expand any of that instance, only then a new HandleMetaClass object will be created -- just for that particular object; and this time HandleMetaClass will be holding not MetaClassImpl, but ExpandoMetaClass instead.

See the screenshot below,

Now, to answer your question, this.metaClass is a special case, like this itself. It doesn't give you the handle, HandleMetaClass object, so you can't expand over metaClass of this -- directly; and there is no sense in that either, because then all other future instances will share that expansion.

If you really want that behaviour then you can pass this to some other variable, i.e. instance = this, as you did in the constructor, and then you can expand over that instance -- and that expansion would be true for this and all other future instances. But then, why not add the behaviour to class itself, in the first place. Why expand?



来源:https://stackoverflow.com/questions/45404442/groovy-instance-metaclass-vs-this-metaclass

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!