将 Java-方法调用传递给 Scala class/method

Pass Java-method-call to Scala class/method

我必须处理这个用 Java 编写的庞大的整体代码,并且有数百个代码重复,例如:

createButtonOne() {
    ... 
    public boolean pressed() {
        doSomething();
        return true;
    }
}

createButtonTwo() {
    ...
    public boolean pressed() {
        doAnotherThing();
        return true;
    }
}

除了调用的函数之外,代码字面意思是一样的,但它很烦人。当然,我可以将大部分方法外包出去,但这会比使用更好的工具正确地花费更多的时间。大概我是这么想的。

我想做的是:

ScalaButton buttonOne = new ScalaButton();
buttonOne.create("Label", Controller.doSomething());

ScalaButton buttonTwo = new ScalaButton();
buttonTwo.create("Label2", Controller.doAnotherThing());

因此我创建了 ScalaButton 如下:

class ScalaButton
{
    def create(label:String, action: () => Unit): Unit = 
    {
        val button:Button = singletonCreator.createButton(label);
        button.addListener(new InputListener()
        {
            override def pressed(...)
            {
                action()
                true
            }
        }
}

问题是我从来没有从 Java 打过这个电话,它说

found void, required scala.Function0

所以我想知道,是否有可能以这种(或另一种)方式将 java 方法调用传递给 Scala?我已经有几个月没有使用 Java 了,也从未以这种方式将它与 Scala 一起使用...

它不会编译,因为您没有将方法传递给 ScalaButton.create,您传递的是方法调用的结果,即 void.

如果你想从Java传递一个函数给Scala,你需要构造一个实例-在这个例子中-AbstractFunction0<BoxedUnit>,它对应于() => Unit.

为此,您需要:

import scala.AbstractFunction0
import scala.runtime.BoxedUnit

然后:

buttonOne.create("Label", new AbstractFunction0<BoxedUnit>() {
    @Override
    public BoxedUnit apply() {
        Controller.doSomething()
        return BoxedUnit.UNIT;
    }
});

还有一个 Function0<BoxedUnit>,但您不想使用它 - 它不打算在 Java.

中构建

如您所见,它的使用并不十分简单。不过,如果您使用的是 Java 8,则可以稍微简化一下。

您需要像这样定义一个函数:

private static Function0<BoxedUnit> getBoxedUnitFunction0(Runnable f) {
    return new AbstractFunction0<BoxedUnit>() {

            @Override
            public BoxedUnit apply() {
                f.run();
                return BoxedUnit.UNIT;
            }
        };
}

别忘了import scala.Function0 - 这里没有构建,所以没关系。现在你可以像这样使用它了:

buttonOne.create("Label", getBoxedUnitFunction0(Controller::doSomething));