utilizan usa una relacion puede número las interfaz interfaces instanciar instancia implementar ilimitado herencia entre como clases scala interface lambda syntactic-sugar traits

scala - usa - relacion entre interfaces java



Implementación de la interfaz de un solo método de Scala. (3)

¿Tiene Scala algún azúcar sintáctico para reemplazar el siguiente código:

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

con algo más como:

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

en los casos en que el rasgo / interfaz necesita solo un método para ser implementado? Si no es así, ¿hay alguna posibilidad de tener esta función en Scala en el futuro? Es especialmente útil cuando se trata de clases de Java.

Encontré una pregunta similar hace tres años: ¿ Implementar genéricamente una interfaz Java de método abstracto con un cierre de Scala? La respuesta dice que deberíamos tener la característica en Scala 2.10. He buscado la palabra clave del método abstracto único pero no he encontrado nada. ¿Qué ha pasado con la función?


Los tipos SAM son compatibles con invokeDynamic desde scala-2.12 similar a JDK-8. A continuación se probó el 2.12.3. Las notas de la versión sobre SAM se pueden encontrar aquí: 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") }


Scala tiene soporte experimental para SAM a partir de 2.11, bajo la bandera -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 = $anonfun$1@7861ff33 scala> new Thread(r).run hello world

Edición : Desde la versión 2.11.5, esto también se puede hacer en línea:

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

Las limitaciones habituales sobre el tipo esperado también se aplican:

  • debe definir un solo método abstracto,
  • su constructor principal (si existe) debe ser público, sin argumentos, sin sobrecargas,
  • el método abstracto debe tomar una sola lista de argumentos,
  • El método abstracto debe ser monomorfo.

Según el compromiso original de Adriaan, algunas de esas restricciones pueden levantarse en el futuro, especialmente las dos últimas.


Si bien hacer esto de una manera genérica es ciertamente complicado, si descubrió que realmente solo necesitaba esto para algunos tipos de Java determinados, entonces unas pocas conversiones implícitas simples pueden hacer el trabajo muy bien. Por ejemplo:

val thread = new Thread(() => println("hello world")) thread.start implicit def function0ToRunnable(f:() => Unit):Runnable = new Runnable{def run() = f()}

A veces, tratar de resolver un problema de una manera genérica y completamente reutilizable es un enfoque equivocado si su problema real es más limitado de lo que cree.