隐式转换为Runnable?

时间:2010-06-18 23:28:02

标签: scala runnable implicit-conversion

作为练习,我尝试创建一个隐式转换,它接受一个函数并产生一个Runnable。这样你就可以调用接受Runnable对象的Java方法,并像封闭一样使用它们。

隐式转换很容易:

    implicit def funToRunnable(fun : Unit) = new Runnable() { def run = fun }

但是我不知道怎么称呼它。如何传入一个返回Unit的无参数函数,而不是立即进行评估?例如,我希望以下内容打印“12”,而是打印“21”,因为print("2")会立即进行评估。

    var savedFun : Runnable = null
    def save(r : Runnable) = { savedFun = r }

    save(print("2"))
    print("1")
    savedFun.run()

如何告诉编译器将print("2")视为函数体,而不是一次评估?我尝试过的一些可能性,例如

    save(() => print("2"))

    save(=> print("2"))

不是合法的语法。

5 个答案:

答案 0 :(得分:23)

arg,刚刚回答了我自己的问题。我错误地实现了隐式转换。正确的实施是

implicit def funToRunnable(fun: () => Unit) = new Runnable() { def run() = fun() }

你这样称呼它:

save(() => print("2"))

这将产生“2”

答案 1 :(得分:12)

如果你想生活危险,你可以将任何东西转换成可运行的东西:

implicit def whateverToRunnable[F](f: => F) = new Runnable() { def run() { f } }

scala> val t = new Thread(println("Hello"))
t: java.lang.Thread = Thread[Thread-2,5,main]

scala> t.start()
Hello

或者您可以创建自己的线程创建者和启动者:

def thread[F](f: => F) = (new Thread( new Runnable() { def run() { f } } )).start

scala> thread { println("Hi"); Thread.sleep(1000); println("Still here!") }
Hi

scala> Still here!

如果你想返回主题,那么

def thread[F](f: => F) = {
  val t = new Thread( new Runnable() { def run() { f } } )
  t.start()
  t
}

但是所有这些虽然有用,但可能比scala.actors.Futures(仅在2.8上测试)更有用:

scala> import scala.actors.Futures

scala> val x = Futures.future { Thread.sleep(10000); "Done!" }
x: scala.actors.Future[java.lang.String] = <function0>

scala> x.isSet
res0: Boolean = false

scala> x.isSet
res1: Boolean = false

scala> x()   // Waits until the result is ready....
res2: java.lang.String = Done!

答案 2 :(得分:5)

有趣的是,通过这种方式,您可以执行接收Runnable的代码并将其传递给闭包。

请参阅:

scala> new Thread( ()  => print( "Hello" ) ).start()
<console>:5: error: overloaded method constructor Thread with alternatives (java.lang.ThreadGroup,java.lang.Runnable,java.lang.String,Long)java.lang.Thread <and> (java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)java.lang.Thread <and> (java.lang.Runnable,java.lang.String)java.lang.Thread <and> (java.lang.ThreadGroup,java.lang.String)java.lang.Thread <and> (java.lang.String)ja...
       new Thread( ()  => print( "Hello" ) ).start()


scala> implicit def funcToRunnable( func : () => Unit ) = new Runnable(){ def run() = func() }
funcToRunnable: (() => Unit)java.lang.Object with java.lang.Runnable

scala> def doRun( runnable: Runnable ) = runnable.run
doRun: (Runnable)Unit

scala> doRun( () => print("Hola"))
Hola

scala> new Thread(()=>print("Hello")).start()

scala> Hello

答案 3 :(得分:4)

实际上,你可以使用call-by-name参数做得更好:

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

用法:

import concurrent.ExecutionContext.Implicits.global._
execute(print("hello"))

答案 4 :(得分:0)

另一种在不同线程中运行某些代码的方法:

scala.actors.Actor.actor { ...doSomething()... }