首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Groovy: this.metaClass与instance.metaClass

Groovy: this.metaClass与instance.metaClass
EN

Stack Overflow用户
提问于 2015-12-24 08:24:46
回答 1查看 1.1K关注 0票数 8

我在书中遇到了下面的groovy脚本代码。它给我带来了一些奇怪的结果。

代码语言:javascript
代码运行次数:0
运行
复制
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()

它的输出如下:

代码语言:javascript
代码运行次数:0
运行
复制
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@245b4bdcclass人是什么意思?我知道"245b4bdc“可能是对象指针。但是为什么HandleMetaClass和MetaClassImpl的指针值"245b4bdc“相同呢?

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-25 12:52:38

  1. 为什么是this.metaClass != instance.metaClass? 它涉及到坡地的进入。
代码语言:javascript
代码运行次数:0
运行
复制
- 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**.

  1. 为什么this.metaClass.say={->println "say"}将抛出MissingPropertyException?
代码语言:javascript
代码运行次数:0
运行
复制
- 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"}**.

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

代码语言:javascript
代码运行次数:0
运行
复制
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()

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

代码语言:javascript
代码运行次数:0
运行
复制
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)
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34449587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档