用函数值覆盖特征方法

时间:2020-05-13 10:05:07

标签: scala inheritance

说我有这样的特征

trait X {
  def foo(param: String): Int
}

我想用一个函数值覆盖它,我必须这样做:

class XImpl extends X {
  private val fooF: String => Int = ???
  override def foo(param: String): Int = fooF(param)
}

因为以下操作无效

class XImpl extends X {
  override val foo: String => Int = ???
}
/*
       error: class XImpl needs to be abstract. Missing implementation for:
         def foo(param: String): Int // inherited from trait X
                                            ^
       error: value foo overrides nothing.
       Note: the super classes of class XImpl contain the following, non final members named foo:
       def foo(param: String): Int
*/

是否可以通过某种方式直接使用函数值实现/重写trait方法并避免使用转发器?

1 个答案:

答案 0 :(得分:5)

简单的答案是,您不能使用函数值覆盖方法,因为它们不是同一类型。

必须在类的特定实例上调用方法(即使该方法本身不使用该类中的任何字段)。

函数值是独立存在的,无需任何其他信息即可调用。

可以使用eta expansion x.foo _将方法转换为函数值。这样会创建一个函数值,其中嵌入了类值。

val x: X = ???
val etaFoo: String => Int = x.foo _

在这种情况下,Scala实际上会为您执行eta扩展,因此_是可选的,但是在更复杂的用途中它是必需的,并且是将其保留在此处的良好实践,因此表明eta扩展正在发生。 / p>

要将函数值转换为方法,您需要定义一个方法,如问题所示。


Eta扩展适用于具有多个参数的方法:

trait X2 {
  def foo2(p1: String, p2: Int): String
}

val x2: X2 = ???
val etaFoo2: (String, Int) => String = x2.foo2 _