gpt4 book ai didi

Groovy:this.metaClass 与 instance.metaClass

转载 作者:行者123 更新时间:2023-12-04 08:42:22 29 4
gpt4 key购买 nike

我在书中遇到过以下 groovy 脚本代码。它给我带来了一些奇怪的输出。

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

它的输出如下:
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

所以我很困惑:
  • 为什么 this.metaClass 不等于 instance.metaClass?
  • 此外,我不能使用 this.metaClass 注入(inject)新方法; groovy 告诉我 this.metaClass 没有我打算注入(inject)的此类属性。
  • “org.codehaus.groovy.runtime.HandleMetaClass@245b4bdc[groovy.lang.MetaClassImpl@245b4bdc[class Person]]”是什么意思?我知道“245b4bdc”可能是对象指针。但是为什么 HandleMetaClass 和 MetaClassImpl 有相同的指针值“245b4bdc”呢?

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

    最佳答案

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

    它涉及groove对字段的访问。
  • 当从“”外部“”访问实例字段时,groovy实际上调用了函数getFieldName()。在我的示例中,当我使用“ instance ”时,我在 外部 ;所以 instance.metaClass 将调用 instance.getMetaClass()
  • 当从“”内部的“”访问实例字段时,groovy 直接访问该字段,不会调用getFieldName()。在我们的示例中,当我使用“ this ”时,我位于“ 内的 ”;所以“ this.metaClass ”将直接访问“ metaClass ”。
  • 最后,getMetaClass() 返回一个 HandleMetaClass 对象,而内部 metaClass 是一个 MetaClassImpl 对象。所以 this.metaClass!=instance.metaClass
  • 为什么this.metaClass.say={->println "say"}会抛出MissingPropertyException?
  • this.metaClass的类型是MetaClassImpl
  • MetaClassImpl是一个低级类,支持上层类(如HandleMetaClass)进行注入(inject)。不适合开发者直接使用,所以不支持注入(inject)方式: xxxx.say={->println "say"}

  • 代码示例(针对问题 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()

    代码示例(对于问题 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,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34449587/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com