【问题标题】:Pass Java-method-call to Scala class/method [duplicate]将 Java 方法调用传递给 Scala 类/方法 [重复]
【发布时间】:2015-07-20 08:25:33
【问题描述】:

我必须处理这个用 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 调用过这个调用,它说

发现无效,需要 scala.Function0

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

【问题讨论】:

  • Controller 是用 Java 还是 Scala 编写的?
  • @EdStaub 目前一切都是用 Java 编写的。
  • @SethTisue Scala 和 Java 都在 2011 年进化,所以我看不到重复。我对您之前发布的问题进行了深入研究。

标签: java scala methods parameters


【解决方案1】:

由于您没有将方法传递给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&lt;BoxedUnit&gt;,但您不想使用它 - 它不是用 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));

【讨论】:

  • 所以如果不使用 Java 8,我会用其他(相当无用的)内联函数替换几十个(相当无用的)内联函数吗?我想拥有像“buttonOne.create("Label", method()") 这样的抽象,而不必再次定义回调:((正如我所看到的那样,使用这种方法我不会获得任何东西 :()
  • 很遗憾,没有 - 方法引用(如 Controller::doSomething)仅在 Java 8 中受支持。没有很好的方法可以让 Java 理解 Scala 的抽象。
  • 很遗憾,但非常感谢您的澄清。提醒我总是在我自己的(和/或新的)项目中使用 Scala :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-01
相关资源
最近更新 更多