Groovy缺失法

Groovy缺失法,groovy,Groovy,我正试图根据文档动态地向Groovy类添加一个新方法。 下面是我实现methodMissing方法的类: class AlexTest { def methodMissing(String name, args){ println "Method missing is called" def cachedMethod = { Object[] varArgs -> println "Hi! ${varArgs}"

我正试图根据文档动态地向Groovy类添加一个新方法。 下面是我实现methodMissing方法的类:

class AlexTest {

    def methodMissing(String name, args){
        println "Method missing is called"

        def cachedMethod = { Object[] varArgs ->
            println "Hi! ${varArgs}"
        }

        AlexTest.metaClass."${name}" = cachedMethod
        return cachedMethod(args)
    }
}
下面是另一个使用AlexTest类的groovy脚本:

def alexTest = new AlexTest()
alexTest.hi("Alex")
alexTest.hi("John")
我希望“methodmissingscalled”只被调用一次,因为方法“hi”会被“引入”到methodMissing中。但是,methodMissing被调用了两次,就好像“hi”方法从未被引入到AlexTest类中一样

我也尝试了不同的做法:

class AlexTest {

    AlexTest() {
        def mc = new ExpandoMetaClass(AlexTest, false, true)
        mc.initialize()
        this.metaClass = mc
    }

    def methodMissing(String name, args){
        println "Method missing is called"

        def cachedMethod = { Object[] varArgs ->
            println "Hi! ${varArgs}"
        }

        // note that this is calling metaClass inside the instance
        this.metaClass."${name}" = cachedMethod
        return cachedMethod(args)
    }
}
哪种方法有效,但只适用于单个实例。因此,如果我创建两个AlexTest实例,并调用'hi'方法,我将得到两条“methodmissing is called”消息。 有人能告诉我解释这种行为的文档吗

提前谢谢

问候,


Alex

在第一次尝试开始时添加以下内容:

ExpandoMetaClass.enableGlobally()
它适用于我的v2.0.1版本

如果希望在类实例的基础上启用,请说明一种方法:

class AlexTest {
    AlexTest() {
        def mc = new ExpandoMetaClass(AlexTest, false, true)
        mc.initialize()
        this.metaClass = mc        
    }

    def methodMissing(String name, args){
        println "Method missing is called"

        def cachedMethod = { Object[] varArgs ->
            println "Hi! ${varArgs}"
        }

        this.metaClass."${name}" = cachedMethod
        return cachedMethod(args)
    }
}

def alexTest = new AlexTest()
alexTest.hi("Alex")
alexTest.hi("John")

这个剧本怎么样?这确保methodMissing为类引用实现,并应用于引用它的所有实例

class AlexTest {

}

mc = AlexTest.metaClass
mc.methodMissing = {String name, args=[:] ->
        println "Method missing is called"
        def cachedMethod = { Object[] varArgs ->
            println "Hi! ${varArgs}"
        }
        mc."${name}" = cachedMethod
        cachedMethod(args)
}

def alexTest = new AlexTest()
alexTest.hi("Alex")
alexTest.hi("John")

def myTest = new AlexTest()
myTest.hi("Walter")
myTest.hi("Hank")

//Prints
Method missing is called
Hi! [Alex]
Hi! [John]
Hi! [Walter]
Hi! [Hank]

尽管在全局范围内启用ExpandoMetaClass同样有效,但只需花费很少的额外内存。:)

但它需要大量内存。:)迈克尔·复活节:是的,我的剧本底部有这个。但正如你提到的,它是每个实例。不是全班的。因此,每当在全新实例上调用“hi”方法时,“methodMissing”就会被调用。这不是我想要的。嗯。。。正如dmahapatro指出的(以及从javadoc中),ExpandoMetaClass.enableglobal()似乎是内存密集型的。但我不确定它的强度有多大。另外,我应该在哪里调用此方法,比如在web应用程序中?在上下文初始化过程中?我已经尝试过了,而且效果很好。我不喜欢它的原因是因为我想在AlexTest类本身中保留“methodMissing”。我不确定在一个完整的应用程序中,在哪里放置该方法是合适的。我想我来自Java背景,所有东西都必须在一个类中。如果AlexTest已经期望“hi”,那么最好在
AlexTest
中实现
hi()
。我希望你明白了。是的,我同意。在这个特定的示例中,最好直接在AlexTest中实现hi()。但我说的是生成动态方法,比如GORM中的finder方法。我很好奇戈姆是怎么做到的。是否使用ExpandoMetaClass.EnableGlobal()?不,他们不使用该设置。所有可能的动态方法都以
grails数据存储gorm
模块中的
finder
的形式出现在
grails数据映射中,并在运行时使用反射将其添加到域类中。要看的类是。也可以浏览@检察官