You get MissingMethodException
你打电话时mc.foo(5)
,因为Groovy的invoke对象方法机制被触发。为了更好地理解这种情况,有一点值得解释。你的MyCallable
class:
class MyCallable {
Foo foo = new Foo()
}
被编译成这样:
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class MyCallable implements GroovyObject {
private Foo foo;
public MyCallable() {
CallSite[] var1 = $getCallSiteArray();
Object var2 = var1[0].callConstructor(Foo.class);
this.foo = (Foo)ScriptBytecodeAdapter.castToType(var2, Foo.class);
MetaClass var3 = this.$getStaticMetaClass();
this.metaClass = var3;
}
public Foo getFoo() {
return this.foo;
}
public void setFoo(Foo var1) {
this.foo = var1;
}
}
Groovy 还编译每个字段访问,例如mc.foo
到 getter 方法调用mc.getFoo()
。所以当你打电话时mc.foo(5)
很明显,对于 Groovy 运行时,您希望调用foo(5)
方法上mc
目的。并且这个方法不存在并且MissingMethodException
被抛出。
但是,如果您创建对象,它就会起作用def foo = new Foo()
然后你打电话foo(5)
, 因为foo
是一个对象并且foo(5)
是一个严格的调用指令call(5)
方法上foo
目的 (foo(5)
是一个简写版本foo.call(5)
)。如果你打电话,也会发生同样的情况mc()
- Groovy 会尝试调用mc.call()
方法。但是当你说mc.foo(5)
很明显你正在尝试调用foo(5)
method.
如果您想使用呼叫操作员mc.foo
字段有两个选项:
1.使用直接字段访问运算符@
mc.@foo(5)
在这种情况下,您可以直接参考foo
字段,您可以使用速记呼叫运算符。
2. Use with {}
method
mc.with {
foo(5)
}
在这种情况下,您正在访问的 Groovy 运行时也是一个简单的方法foo
字段,您可以在其上使用呼叫运算符。
备择方案
使用getter方法:
mc.getFoo()(5)
使用方法call()
直接地:
mc.foo.call(5) // equivalent of mc.getFoo().call(5)