Groovy:this.metaClass与instance.metaClass
我在书中遇到了下面的groovy脚本代码。它给我带来了一些奇怪的结果Groovy:this.metaClass与instance.metaClass,groovy,this,metaclass,Groovy,This,Metaclass,我在书中遇到了下面的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 c
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
所以我很困惑:
- 当从外部访问实例字段时,groovy实际上调用函数getFieldName()。在我的示例中,当我使用“实例”时,我位于外部;因此,instance.metaClass将调用instance.getMetaClass()
- 当从“”内部访问实例字段时,groovy只需直接访问该字段,不调用getFieldName()。在我们的示例中,当我使用“this”时,我位于“内部””;因此“this.metaClass”将直接访问“metaClass”
- 最后,getMetaClass()返回一个HandleMetaClass对象,而内部元类是一个MetalassImpl对象。所以这个元类=实例.元类
- 元类的类型是MetaClassImpl
- MetaClassImpl是一个低级类,它支持用于注入的高级类(例如HandleMetaClass)。它不适合开发人员直接使用,因此不支持注入方式:xxxx.say={->println“say”}
如果将其更改为
assert this.class.metaClass==instance.metaClass
,它将通过。为什么?应该this.class.metaClass==Person.metaClass吗?在这里找到了一个更好的答案,实际上,那就是我。那么,当当前类中没有定义metaClass
时,它是如何进行字段访问的呢?也许它的访问修饰符在它的对象超类中受到保护,也许?但在任何情况下,根据groovy文档,为了获得字段访问权,需要从定义属性的类中访问属性<代码>元类
未在Person子类中定义,因此我想知道字段访问是如何完成的。
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()
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)