我正在尝试按照文档动态地向我的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")
我希望只调用一次“方法缺失被调用” - 因为方法“hi”将在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'方法,我将得到两个“Method missing is called”消息。 有人能指出我解释这种行为的文件吗?
提前致谢!
此致
亚历
答案 0 :(得分:1)
在第一次尝试开始时添加以下内容:
ExpandoMetaClass.enableGlobally()
它适用于V 2.0.1
如果您希望在基于类实例的基础上启用,this post说明了一种方法:
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")
答案 1 :(得分:0)
脚本中的这个怎么样?这样可以确保为Class引用实现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也可以带来额外的内存成本。 :)
答案 2 :(得分:0)
另一种解决方案是在 Map
中缓存方法闭包。
class AlexTest {
static Map methods = [:]
def methodMissing(String name, args){
if (!methods[name]) {
println "Method is not cached"
methods[name] = { Object[] varArgs ->
println "Hi! ${varArgs}"
}
}
return methods[name](args)
}
}
def alexTest = new AlexTest()
alexTest.hi("Alex")
alexTest.hi("John")
输出
Method is not cached
Hi! [Alex]
Hi! [John]