通过将函数作为参数传递来实现Scala特征

时间:2014-03-20 18:50:45

标签: scala

假设我们有Scala特征

trait Foo {
  def bar(baz: Qux): Quux
  def corge: Grault
}

我们希望以这样一种方式实现它,即bar()的实现可以由匿名函数处理。我们可以这样做:

class FooImpl1(_bar: (Qux) => Quux, val corge: Grault) extends Foo {
  override def bar(baz: Qux) = { _bar(baz) }
}

允许,例如:

val foo: Foo = new FooImpl({ qux: Qux => qux.asQuux()}, someGrault)

但这似乎不必要地冗长(并且还引入了可怕的,笨重的,领先的下划线)。

天真地注意到def corge Foo中的val corge是由FooImpl1 class FooImpl2(val bar: (Qux) => Quux, val corge: Grault) extends Foo {} 实现的,似乎应该可以这样做:

Foo.bar

但是我们不能,大概是因为FooImpl1 返回一个函数,它一个函数(或者更确切地说是一个方法)。

我们可以在这里做些比{{1}}更清洁的事吗?

2 个答案:

答案 0 :(得分:1)

如果你控制了这个特性,你可以尝试修改它:

trait Foo {
  val bar: Function1[Qux, Quux]
  def corge: Grault
}

使您的FooImpl2定义成为可能。这是Eclipse ScalaWorksheet的一个例子:

package so

object ClassExperiment {
  type Qux = Int
  type Quux = Boolean
  type Grault = String

  trait Foo {
    val bar: Function1[Qux, Quux]
    def corge: Grault
  }

  class FooImpl2(val bar: (Qux) => Quux, val corge: Grault) extends Foo {
    def blue = bar( 9 )
  }

  val foo = new FooImpl2( { a: Qux => a == 4 }, new Grault("monkey") )
                                                  //> foo  : so.ClassExperiment.FooImpl2 = so.ClassExperiment$FooImpl2@68f
                                                  //| e748f

  foo.blue                                        //> res0: so.ClassExperiment.Quux = false
  foo.bar( 4 )                                    //> res1: so.ClassExperiment.Quux = true
  foo.bar( 7 )                                    //> res2: so.ClassExperiment.Quux = false
  foo.corge                                       //> res3: so.ClassExperiment.Grault = monkey
}

我在创建Foo时没有关闭foo类型说明符,因此我可以将调用输出显示给blue

答案 1 :(得分:0)

为什么不这样做?

val foo = new Foo { 
   def bar(qux : Qux) = qux.asQuux 
   val corge = someGrault
}

看起来定义一个FooImpl类真的没什么可买的。