如果我写:
trait Aaa {
def a(i: Int): Boolean
}
class Bbb extends Aaa {
def a = (x: Int) => x == 42
}
但是它无法编译,我收到以下错误:
override.scala:7: class Bbb needs to be abstract, since method a in trait Aaa of type (i: Int)Boolean is not defined
class Bbb extends Aaa {
^
Compilation Failed
为什么?
特征Aaa
规定必须有一个方法a
,其中包含一个类型为Int
的参数并返回类型Boolean
。
类Bbb
有一个不带任何参数的方法a
,返回类型(Int => Boolean)
,这与Function1[Int, Boolean]
相同。
因此,Bbb
中a
的方法具有错误的参数数和不同的返回类型。
它不应该编译,所以它不会编译。没有任何问题。
一般评论:
def f(x1: T1, ..., xn: Tn): Y = body
不是句法糖
val f = (x1: T1, ..., xn: Tn): Y => body
前者是方法,后者是类型为FunctionN[T1, ..., Tn, Y]
的值。虽然这两个定义在受ML影响的其他一些语言中可能以相同的方式处理,但在Scala中并非如此。Scala 区分方法和函数。
特征Aaa
定义方法a
但类Bbb
定义函数值a
。方法与函数值不同是 Scala,因此类Bbb
中a
的定义不会实现Aaa
中的a
。由于Aaa.a
没有定义,因此必须将类声明为abstract
。
如果您改为这样做,它将起作用:
class Bbb extends Aaa {
def a(x:Int) = x == 42
}
如果你真的需要一个函数值而不是一个方法,你需要声明另一个val
并使用像这样的eta 扩展:
class Bbb extends Aaa {
def a(x:Int) = x == 42
val b = a _
}
b
现在可以作为函数参数传递给诸如filter
之类的调用,而a
则不能。