Можно ли использовать ссылки на метод стиля Java 8 в Scala?

Я разрабатываю приложение JavaFX8 в Scala, но я не мог понять, как передать ссылку на метод обработчику событий. Чтобы уточнить, я не использую библиотеку 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? Я знаю о неявном методе конверсий для использования выражения лямбда, но я хочу знать, есть ли способ использовать ссылку на метод, аналогичную Java 8, без необходимости использования лямбда-декларации.

Ответы

Ответ 1

inputController::handleFileSelection - синтаксис Java, который не поддерживается или не нужен в Scala, потому что у него уже был короткий синтаксис для lambdas: inputController.handleFileSelection _ или inputController.handleFileSelection(_) (inputController.handleFileSelection также может работать, в зависимости от контекст).

Однако в Java вы можете использовать lambdas и ссылки на методы, когда ожидается любой интерфейс SAM (один абстрактный метод), а EventHandler - это просто такой интерфейс. В Scala до версии 2.11 это вообще не допускается, в версии 2.11 имеется экспериментальная поддержка использования lambdas с интерфейсами SAM, которая должна быть включена с использованием флага -Xexperimental scalac, а начиная с 2.12 она полностью поддерживается и не работает 't необходимо включить.

Ответ 2

Вам следует передать функцию, которая применяет один параметр типа 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))