说我有这样的特质
trait X {
def foo(param: String): Int
}
Run Code Online (Sandbox Code Playgroud)
我想用函数值覆盖它,我必须这样做:
class XImpl extends X {
private val fooF: String => Int = ???
override def foo(param: String): Int = fooF(param)
}
Run Code Online (Sandbox Code Playgroud)
因为以下不起作用
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
*/
Run Code Online (Sandbox Code Playgroud)
是否可以以某种方式直接实现/覆盖具有函数值的 trait 方法并避免转发器?
简单的答案是,您不能使用函数值覆盖方法,因为它们的类型不同。
必须在类的特定实例上调用方法(即使方法本身不使用该类中的任何字段)。
一个函数值是独立的,可以在没有任何附加信息的情况下被调用。
可以使用eta 扩展 将方法转换为函数值x.foo _。这将创建一个函数值,其中嵌入了类值。
val x: X = ???
val etaFoo: String => Int = x.foo _
Run Code Online (Sandbox Code Playgroud)
在这种情况下,Scala 实际上会为您进行 eta 扩展,因此它_是可选的,但在更复杂的用途中是必需的,并且将其保留在那里是一种很好的做法,以便表明 eta 扩展正在发生。
要将函数值转换为方法,您需要定义一个方法,如问题所示。
Eta 扩展适用于具有多个参数的方法:
trait X2 {
def foo2(p1: String, p2: Int): String
}
val x2: X2 = ???
val etaFoo2: (String, Int) => String = x2.foo2 _
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
57 次 |
| 最近记录: |