Groovy调用运算符在类字段上使用时引发MissingMethodException [英] Groovy call operator throws MissingMethodException when used on a class field

查看:113
本文介绍了Groovy调用运算符在类字段上使用时引发MissingMethodException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用调用运算符()重载,但是它不适用于类字段.怎么了?

I am trying to use call operator () overloading, but it does not work on class fields. What's wrong?

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课:

You get MissingMethodException when you call mc.foo(5), because Groovy's invoke object method mechanism gets triggered. There is one thing worth explaining to get a better understanding about this situation. Your 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运行时很明显,您希望在mc对象上调用foo(5)方法.而且此方法不存在,并且会抛出MissingMethodException.

Groovy also compiles every field access like mc.foo to a getter method call mc.getFoo(). So when you call mc.foo(5) it is clear for Groovy runtime that you expect to call a foo(5) method on mc object. And this method does not exist and MissingMethodException gets thrown.

但是,如果创建对象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)方法.

However, it works if you create object def foo = new Foo() and then you call foo(5), because foo is an object and foo(5) is a strict instruction to invoke call(5) method on foo object (foo(5) is a shorthand version of foo.call(5)). The same situation would take place if you call mc() - Groovy would try to invoke mc.call() method. But when you say mc.foo(5) it's clear that you are trying to invoke foo(5) method.

如果要在mc.foo字段上使用呼叫运算符,则有两种选择:

If you want to use call operator on mc.foo field there are two options:

mc.@foo(5)

在这种情况下,您直接引用foo字段,并且可以使用速记呼叫运算符.

In this case you refer directly to foo field and you can use shorthand call operator.

mc.with {
    foo(5)
}

在这种情况下,对于Groovy运行时来说,访问foo字段也是很简单的,并且可以在其上使用调用运算符.

In this case it is also a straightforward for Groovy runtime that you are accessing foo field and you can use call operator on it.

使用getter方法:

Using getter method:

mc.getFoo()(5)

直接使用方法call():

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

这篇关于Groovy调用运算符在类字段上使用时引发MissingMethodException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆