Подтвердить что ты не робот

Scala реализация интерфейса одного метода

Имеет ли Scala какой-либо синтаксический сахар для замены следующего кода:

val thread = new Thread(new Runnable {
   def run() {
     println("hello world")
   }    
})

с чем-то более похожим:

val thread = new Thread(() => println("hello world"))

в случаях, когда для свойства/интерфейса требуется только один метод для реализации? Если нет, есть ли шанс получить эту функцию в Scala в будущем? Это особенно полезно, когда речь идет о Java-классах.

Я нашел аналогичный вопрос, заданный три года назад: В целом реализация интерфейса Java Single-Abstract-Method с закрытием Scala? В ответе говорится, что мы должны иметь функция в Scala 2.10. Я искал ключевое слово Single Abstract Method, но ничего не нашел. Что случилось с этой функцией?

4b9b3361

Ответ 1

Scala имеет экспериментальную поддержку для SAM, начиная с 2.11, под флагом -Xexperimental:

Welcome to Scala version 2.11.0-RC3 (OpenJDK 64-Bit Server VM, Java 1.7.0_51).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :set -Xexperimental

scala> val r: Runnable = () => println("hello world")
r: Runnable = [email protected]

scala> new Thread(r).run
hello world

Изменить. Начиная с версии 2.11.5 это также можно сделать inline:

scala> new Thread(() => println("hello world")).run
hello world

Также применяются обычные ограничения на ожидаемый тип:

  • он должен определить один абстрактный метод,
  • его основной конструктор (если он есть) должен быть общедоступным, no-args, а не перегружен,
  • абстрактный метод должен принимать один список аргументов,
  • абстрактный метод должен быть мономорфным.

В соответствии с оригинальной фиксацией Adriaan, некоторые из этих ограничений могут быть отменены в будущем, особенно последние два.

Ответ 2

При выполнении этого в общем случае, безусловно, сложно, если вы обнаружили, что вам действительно нужно это только для некоторых определенных типов Java, тогда несколько простых неявных преобразований могут хорошо выполнять работу. Например:

val thread = new Thread(() => println("hello world"))
thread.start

implicit def function0ToRunnable(f:() => Unit):Runnable = 
  new Runnable{def run() = f()}

Иногда попытка решить проблему общим и полностью повторно используемым способом - это неправильный подход, если ваша фактическая проблема более ограничена, чем вы думаете.

Ответ 3

Типы SAM поддерживаются с помощью invokeDynamic, так как scala-2.12 похож на JDK-8, ниже был протестирован на 2.12.3. Замечания о выпуске SAM можно найти здесь - http://www.scala-lang.org/news/2.12.0/

object ThreadApp extends App {
  println("Main thread - begins")
  val runnable: Runnable = () => println("hello world - from first thread")

  val thread = new Thread(runnable)
  println("Main thread - spins first thread")
  thread.start()

  val thread2 = new Thread(() => println("hello world - from second thread"))
  println("Main thread - spins second thread")
  thread2.start
  thread.join()
  thread2.join()

  println("Main thread - end")
}