【发布时间】:2016-03-30 17:01:42
【问题描述】:
我在书中遇到过下面的 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来注入新方法; groovy 告诉我 this.metaClass 没有我打算注入的此类属性。
- “org.codehaus.groovy.runtime.HandleMetaClass@245b4bdc[groovy.lang.MetaClassImpl@245b4bdc[class Person]]”是什么意思?我知道“245b4bdc”可能是对象指针。但是为什么 HandleMetaClass 和 MetaClassImpl 的指针值相同“245b4bdc”?
目前,我发现@245b4bdc 不是“对象引用”,所以 HandleMetaClass@245b4bdc 不一定是与 MetaClassImpl@245b4bdc 相同的实例。我们可以使用 Object.is() 方法来判断它们是否相同。(我这样做了,结果是 false)
【问题讨论】:
-
如果你把它改成
assert this.class.metaClass == instance.metaClass,它就会通过。 -
为什么? this.class.metaClass == Person.metaClass 应该吗?
-
在这里找到了更好的答案,stackoverflow.com/a/45407488/42769,其实就是我。