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

在groovy中,当比较此引用和方法中传递的引用时:相同的实例,不同的元类,groovy,metaclass,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: gree

在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)
最奇怪的是,
断言this==self
实际传递,这意味着它们是同一个实例。。。正确的?默认的
toString
似乎也证实了这一点

另一方面,
断言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的引用的情况下工作?

您可以在课堂上实现
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中的
==
实际上意味着
等于()
(即值比较),如果要比较标识,则可以使用
is()
,如下所示

a.is(b) //Corresponds to == in Java
a == b //Corresponds to equals() in Java
更新
可以使用元类,如下所示

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

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

greet.sayHello()

您可以在下面的课程中实现
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中的
==
实际上意味着
等于()
(即值比较),如果要比较标识,则可以使用
is()
,如下所示

a.is(b) //Corresponds to == in Java
a == b //Corresponds to equals() in Java
更新
可以使用元类,如下所示

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

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

greet.sayHello()

我想出了两个问题:

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

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


查看此链接:

我想出了两个问题:

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

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


请参阅此链接:

谢谢。不知道为什么我一开始没有使用methodMissing。我认为这与内部类有关,但现在它起作用了。不知道a.is(b),尽管断言这个.is(self)仍然成功。@PelleWielinga如果我需要立即测试或创建测试,我更喜欢元类。要回答第一个问题,请参阅my updates.Greeter.metaClass.greeting静态定义它,这对我来说是个问题。greet.metaClass.greeting有效,但this.metaClass.greeting无效,这对我来说仍然是个谜。@PelleWielinga Nope,
Greeter.metaClass.greeting={..}
不应将其定义为静态。对于静态方法,使用了
Greeter.metaClass.static.greeting={..}
。哦,对了,方法本身不是静态的,但它是为所有未来(和过去?)实例定义的。我的方法因实例而异,现在我用methodMissing引用的映射解决了这个问题。下次我会尝试找到一个与我的实际问题更密切相关的例子:)谢谢。不知道为什么我一开始没有使用methodMissing。我认为这与内部类有关,但现在它起作用了。不知道a.is(b),尽管断言这个.is(self)仍然成功。@PelleWielinga如果我需要立即测试或创建测试,我更喜欢元类。要回答第一个问题,请参阅my updates.Greeter.metaClass.greeting静态定义它,这对我来说是个问题。greet.metaClass.greeting有效,但this.metaClass.greeting无效,这对我来说仍然是个谜。@PelleWielinga Nope,
Greeter.metaClass.greeting={..}
不应将其定义为静态。对于静态方法,使用了
Greeter.metaClass.static.greeting={..}
。哦,对了,方法本身不是静态的,但它是为所有未来(和过去?)实例定义的。我的方法因实例而异,现在我用methodMissing引用的映射解决了这个问题。下次我将尝试找到一个与我的实际问题更密切相关的示例:)我遇到了相同的问题:。您解决了this.metaClass问题吗?我遇到了相同的问题:。你解决这个元类的问题了吗?