Groovy调用运算符在类字段上使用时引发MissingMethodException

Groovy调用运算符在类字段上使用时引发MissingMethodException,groovy,Groovy,我试图使用call操作符()重载,但它对类字段不起作用。怎么了 class Foo { void call(int x){ println("x="+x) } } class MyCallable { Foo foo = new Foo() } Foo foo = new Foo() foo(5) //works MyCallable mc = new MyCallable() mc.foo(2) //not works 但程序异常终止: Ex

我试图使用call操作符
()
重载,但它对类字段不起作用。怎么了

class Foo {
    void call(int x){
        println("x="+x)
    }
}

class MyCallable {
    Foo foo = new Foo()
}

Foo foo = new Foo() 
foo(5)  //works

MyCallable mc = new MyCallable()
mc.foo(2) //not works
但程序异常终止:

Exception in thread "main" groovy.lang.MissingMethodException: No
signature of method: mpctests.MyCallable.foo() is applicable for
argument types: (java.lang.Integer) values: [2]

调用
mc.foo(5)
时,您会得到
MissingMethodException
,因为Groovy的调用对象方法机制会被触发。有一件事值得解释,以便更好地了解这种情况。您的
MyCallable
类:

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运行时显然希望调用
mc
对象上的
foo(5)
方法。并且此方法不存在,将抛出
MissingMethodException

但是,如果您创建object
def foo=new foo()
,然后调用
foo(5)
,它是有效的,因为
foo
是一个对象,
foo(5)
是调用
foo
对象上的
call(5)
方法的严格指令(
foo(5)
foo.call(5)
的简写版本)。如果调用
mc()
,同样的情况也会发生——Groovy将尝试调用
mc.call()
方法。但是当您说
mc.foo(5)
时,很明显您正在尝试调用
foo(5)
方法


如果您想在
mc.foo
字段上使用call operator,有两个选项:

1.使用直接现场访问操作员
@
在这种情况下,您可以直接参考
foo
字段,并使用速记呼叫接线员

2.将
与{}
方法一起使用 在本例中,对于Groovy运行时来说,访问
foo
字段也很简单,您可以对其使用call操作符

选择 使用getter方法:

mc.getFoo()(5)
直接使用方法
call()

mc.foo.call(5) // equivalent of mc.getFoo().call(5)

这是如何编译的呢?另一种方法:
(mc.foo)(
mc.getFoo()(5)
mc.foo.call(5) // equivalent of mc.getFoo().call(5)