web-dev-qa-db-ja.com

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)

コンパイラからのエラーメッセージは次のとおりです(Scala2.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)のようなメソッド参照を使用する方法があるかどうかを知りたい。

27
Mustafa

_inputController::handleFileSelection_ is Java構文、これはScalaでサポートされていないか、必要ありません。これは、ラムダの短い構文がすでにあるためです:_inputController.handleFileSelection __またはinputController.handleFileSelection(_)(_inputController.handleFileSelection_も、コンテキストに応じて機能します)。

ただし、Javaでは、SAM(単一抽象メソッド)インターフェースが必要な場合にラムダとメソッド参照を使用でき、EventHandlerはまさにそのようなインターフェースです。InScalaバージョン2.11より前では、これはまったく許可されていません。2.11では、SAMインターフェースでラムダを使用するための実験的なサポートがあり、_-Xexperimental_ scalacフラグを使用して有効にする必要があります。2.12以降では、完全にサポートされており、有効にする必要はありません。

17
Alexey Romanov

タイプActionEventの1つのパラメーターを適用する関数を渡す必要があります。

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))
3
Sergey Lagutin