是否可以在Scala中使用Java 8样式方法引用?

我正在Scala中开发JavaFX8应用程序,但我无法弄清楚如何将方法引用传递给事件处理程序。 为了澄清,我没有使用ScalaFX库,而是直接在JavaFX上构建我的应用程序。

这是相关的代码段。

InputController.java (我用Java编写了这个测试类来隔离问题,只使用方法引用)

public class InputController { public void handleFileSelection(ActionEvent actionEvent){ //event handling code } public InputController() { //init controller } } 

这工作(Java)

 InputController inputController = new InputController(); fileButton.setOnAction(inputController::handleFileSelection); 

这不起作用(Scala)

 val inputController = new InputController fileButton.setOnAction(inputController::handleFileSelection) 

这是编译器的错误消息(Scala 2.11.6)。

 Error:(125, 45) missing arguments for method handleFileSelection in class Main; follow this method with '_' if you want to treat it as a partially applied function fileButton.setOnAction(inputController::handleFileSelection) ^ 

如果我使用Scala 2.12.0-M2,我会收到不同的错误消息。

 Error:(125, 45) missing argument list for method handleFileSelection in class Main Unapplied methods are only converted to functions when a function type is expected. You can make this conversion explicit by writing `handleFileSelection _` or `handleFileSelection(_)` instead of `handleFileSelection`. fileButton.setOnAction(inputController::handleFileSelection) ^ 

是否存在Scala可以利用Java 8中引入的方法引用的本机方式? 我知道使用lambda表达式的隐式转换方法,但我想知道是否有一种方法可以使用类似于Java 8的方法引用,而无需使用lambda decleration。

inputController::handleFileSelection是Java语法,Scala不支持或不需要它,因为它已经有一个lambdas的短语法,如下所示: inputController.handleFileSelection _inputController.handleFileSelection(_)inputController.handleFileSelection也可以工作,取决于上下文)。

但是,在Java中,当需要任何SAM(单个抽象方法)接口时,您可以使用lambdas和方法引用,而EventHandler就是这样的接口。 在版本2.11之前的Scala中根本不允许这样做,在2.11中有使用带有SAM接口的lambdas的实验性支持,必须使用-Xexperimental scalac标志启用它,并且从2.12开始它完全支持并且不需要要启用。

你应该传递应用ActionEvent类型的一个参数的函数:

 val button = new Button() val inputController = new InputController() def handler(h: (ActionEvent => Unit)): EventHandler[ActionEvent] = new EventHandler[ActionEvent] { override def handle(event: ActionEvent): Unit = h(event) } button.setOnAction(handler(inputController.handleFileSelection))