使用Scala函数而不是类似Java回调的匿名对象

时间:2011-07-13 10:41:45

标签: java scala callback anonymous-function

Java风格的匿名回调包含相对较多的样板,并且不能阅读。有像

这样的东西会很高兴
workExpression

而不是

new SomeIF {
    @Override public someType doRun() {
        return workExpression
    }
}

有哪些可能的解决方案?

2 个答案:

答案 0 :(得分:7)

一种可能的解决方案是使用implicit defs将函数转换为旧的回调类型。例如:

// Required by some API
trait Callable[A] {
  def call(): A
}

trait Processor[A,B] {
  def process(a: A): B
}

// Our helper trait
trait MyImplicits {
  implicit def funToCallable[A](f: () => A) = new Callable[A]() { 
    def call() = f()
  }

  implicit def funToProcessor[A,B](f: (A) => B) = new Processor[A,B]() {
    def process(a: A) = f(a)
  }

}

object App extends MyImplicits {

  def main(args: Array[String]) {
    // Traditional usage
    runSomeCallable(new Callable[String]() {
      def call() = "World"
    })

    runSomeProcessor(new Processor[String,Int] {
      def process(a: String) = a.toInt * 2
    })

    // Usage with implicits
    runSomeCallable(() => "Scala World")

    runSomeProcessor((s: String) => s.toInt * 2)
  }

  // Methods defined by some foreign API
  def runSomeCallable[A](callable: Callable[A]) {
    println("Hello "+callable.call())
  }

  def runSomeProcessor(processor: Processor[String,Int]) {
    println("From 1 to "+processor.process("1"))
  }

}

因此,在处理某些代码时,可以为该代码中使用的常见回调类型创建一个帮助器特征,以便于阅读。

答案 1 :(得分:2)

使用单一方法自动将闭包转换为接口可能会出现在Scala的未来版本中:http://www.scala-lang.org/node/8744这样可以避免带有当前必需的含义的样板。