在groovy中比较这个和方法中传递的引用:相同的实例,不同的元类

时间:2013-08-28 20:20:51

标签: groovy metaclass

在groovy 1.8.6中,我试图做这样的事情:

class Greeter {
    def sayHello() {
        this.metaClass.greeting = { System.out.println "Hello!" }
        greeting()
    }
}

new Greeter().sayHello()

这不起作用:

groovy.lang.MissingPropertyException: No such property: greeting for class: groovy.lang.MetaClassImpl

经过一番尝试后,我发现将对self的引用传递给方法确实有效。所以,基本上我想出的是:

class Greeter {
    def sayHello(self) {
        assert this == self
        // assert this.metaClass == self.metaClass

        self.metaClass.greeting = { System.out.println "Hello!" }
        greeting()
    }
}

def greeter = new Greeter()
greeter.sayHello(greeter)

最奇怪的是assert this == self实际上已经过了,这意味着它们是同一个实例......对吗?默认toString似乎也证实了这一点。

另一方面,assert this.metaClass == self.metaClass失败:

assert this.metaClass == self.metaClass
            |         |  |    |
            |         |  |    org.codehaus.groovy.runtime.HandleMetaClass@50c69133[groovy.lang.MetaClassImpl@50c69133[class Greeter]]
            |         |  Greeter@1c66d4b3
            |         false
            groovy.lang.MetaClassImpl@50c69133[class Greeter] 

为什么self.metaClass包含在HandleMetaClass中,而this.metaClass不包含?另外,如何在不传递对self的引用的情况下使第一个例子工作?

2 个答案:

答案 0 :(得分:1)

我想出了两个问题:

  • groovy.lang.MissingPropertyException:没有这样的属性:类的问候语:groovy.lang.MetaClassImpl

  • 为什么this.metaClass == self.metaClass

请参阅此链接:https://stackoverflow.com/a/45407488/42769

答案 1 :(得分:0)

您可以在课程中实施methodMissing,如下所示,以回答您的上一个问题:

class Greeter {
    def sayHello() {
        //this.metaClass.greeting = { System.out.println "Hello!" }
        greeting()
        goodNight()
    }

    def methodMissing(String name, args){
        if(name == 'greeting'){
            println "Hello!" 
        } else
            println "Good Night"
    }
}

new Greeter().sayHello()

另请注意,groovy中的==实际上意味着equals()(即价值比较),如果您想要比较身份,则is()可以像

一样使用
a.is(b) //Corresponds to == in Java
a == b //Corresponds to equals() in Java

<强>更新
可以使用metaClass如下

Greeter.metaClass.greeting = { println "Hello"}
def greet = new Greeter()

//or
//greet.metaClass.greeting = { println "Hello"}

greet.sayHello()