Groovy instance.metaclass 对比 this.metaclass

Groovy instance.metaclass vs this.metaclass

我有以下脚本:

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

输出为:

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

谁能给我解释一下这是怎么回事?

提前致谢。

看看这个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}"
    }
}

看看groovysh的截图。它可能会给你一些关于正在发生的事情的提示。

  1. pq是两个不同的对象,但是
  2. p.metaClass等同于q.metaClass
  3. printAllpq
  4. 打印完全相同的内容
  5. a.metaClassb.metaClass持有this.class.metaClass,而不是this.metaClass,你看

MetaClassImpl 只创建了一个对象,HandleMetaClass 也只有一个对象,Person。而且无论你实例化多少次Person,它们都会被赋值给实例。但是,当您展开该实例中的任何一个时,只会为该特定对象创建一个新的 HandleMetaClass 对象;这次 HandleMetaClass 持有的不是 MetaClassImpl,而是 ExpandoMetaClass

看下面的截图,

现在,回答你的问题,this.metaClass 是一个特例,就像 this 本身一样。它不会为您提供 HandleMetaClass 对象的句柄,因此您不能直接扩展 thismetaClass;并且这也没有任何意义,因为所有其他未来实例都将共享该扩展。

如果你真的想要那种行为,那么你可以将 this 传递给其他一些变量,即 instance = this,就像你在构造函数中所做的那样,然后你可以扩展 instance -- 并且该扩展对于 this 和所有其他未来实例都是正确的。但是,为什么不首先将行为添加到 class 本身。为什么要扩展?