Scala single method interface implementation

安稳与你 提交于 2019-11-26 17:13:29

问题


Does Scala have any syntactic sugar to replace the following code:

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

with something more like:

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

in cases when the trait/interface needs only one method to be implemented? If not, is there any chance to have this feature in Scala in the future? It is especially useful when one deals with Java classes.

I found a similar question asked three years ago: Generically implementing a Java Single-Abstract-Method interface with a Scala closure? The answer says we should have the feature in Scala 2.10. I've looked for Single Abstract Method keyword but I have not found anything. What's happened with the feature?


回答1:


Scala has experimental support for SAMs starting with 2.11, under the flag -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

Edit: Since 2.11.5, this can also be done inline:

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

The usual limitations about the expected type also apply:

  • it must define a single abstract method,
  • its primary constructor (if any) must be public, no-args, not overloaded,
  • the abstract method must take a single argument list,
  • the abstract method must be monomorphic.

According to the original commit by Adriaan, some of those restrictions may be lifted in the future, especially the last two.




回答2:


While doing this in a generic way is certainly complicated, if you found that you really only needed this for a few certain Java types, then a few simple implicit conversions can do the job nicely. For instance:

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

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

Sometimes trying to solve a problem in a generic and completely re-useable way is the wrong approach if your actual problem is more bounded then you think.




回答3:


SAM types are supported using invokeDynamic since scala-2.12 similar to JDK-8, Below was tested on 2.12.3 - Release notes about SAM can be found here - 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")
}


来源:https://stackoverflow.com/questions/22820352/scala-single-method-interface-implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!