Scala с использованием библиотек Java, используя поддержку лямбда-выражений в Java 8

Согласно: http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#lambda-expressions-in-gui-applications

Ранее:

btn.setOnAction(new EventHandler<ActionEvent>() {

    @Override
    public void handle(ActionEvent event) {
        System.out.println("Hello World!");
    }
});

Теперь мы можем:

btn.setOnAction(
  event -> System.out.println("Hello World!")
);

Теперь я пытаюсь сделать это в Scala при использовании библиотеки Java.

Я использую JavaFX (который включен по умолчанию в Java 1.8 SE). Попробуйте:

chart.setOnMouseClicked( (e: MouseEvent) => println("Noice") )

Однако я получаю:

Error:(204, 46) type mismatch;
 found   : javafx.scene.input.MouseEvent => Unit
 required: javafx.event.EventHandler[_ >: javafx.scene.input.MouseEvent]
    chart.setOnMouseClicked( (e: MouseEvent) => println("Noice") )
                                             ^

Старый стиль отлично работает:

chart.setOnMouseClicked( new EventHandler[MouseEvent] {
  override def handle(event: MouseEvent): Unit = println("NOT NOICE")
} )

Я установил уровень языка проекта на Java 8 в IntelliJ, я использую Scala 2.11.1 и Java от Oracle версии 1.8.0_05

Что мне здесь не хватает? или просто невозможно передать лямбда-выражение из Scala на Java так же, как это сделано в указанном примере?

Ответы

Ответ 1

Для версии scala версии 2.12 поддержка появляется из коробки.

Состояние для pre-2.12:

Lambdas был представлен в java языке и имеет мало общего с функциями scala. Они скомпилированы до другого байт-кода, имеет разную иерархию (функции scala были здесь задолго до этого, и, по-видимому, разработчики java выбрали реализацию чистой комнаты без совместимости с scala).

В настоящее время поддержка в значительной степени ограничена и то, что вы пытаетесь сделать, невозможно (из коробки):

Серия scala 2.11 нацелена на Java 6, с (развивающейся) экспериментальной поддержка Java 8. В версии 2.11 поддержка Java 8 в основном ограничена чтение байт-кода Java 8 и разбор источника Java 8. Мы будем расширение scala (экспериментальное) Java 8 поддержка и взаимодействие по всему серии 2.11. - См. Больше на: https://typesafe.com/blog/scala-211-has-arrived#sthash.ukr4FSpU.dpuf

текущие усилия для решения этой проблемы

См. также обсуждение scala дорожной карты для поддержки функций java 8.

Ответ 2

Одним из способов достижения этого является использование неявных преобразований, что вам нужно сделать, это создать новый Object, который обрабатывает все эти преобразования, примерно так:

import javafx.scene.input.MouseEvent
import javafx.event.EventHandler

object FXEvent2HandlerImplicits{
  implicit def mouseEvent2EventHandler(event:(MouseEvent)=>Unit) = new EventHandler[MouseEvent]{
    override def handle(dEvent:MouseEvent):Unit = event(dEvent)
  }
}

Затем просто импортируйте его в любой файл, который может понадобиться для преобразования:

import FXEvent2HandlerImplicits._   
//From now on within scope you can now call events like Java8 Lambdas
chart.setOnMouseClicked( (e: MouseEvent) => println("Noice") )

Это просто синтаксический сахар, чтобы архивировать то же самое более элегантным способом.