如果我写:
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
为什么?
答案 0 :(得分:3)
特征Aaa
规定必须有一个方法a
,其中一个参数类型为Int
,返回类型为Boolean
。
类Bbb
的方法a
没有任何参数,返回类型(Int => Boolean)
,与Function1[Int, Boolean]
相同。
因此,a
中的方法Bbb
包含错误的参数数量和不同的返回类型。
它不应该编译,因此它不会编译。没问题。
一般性评论:
def f(x1: T1, ..., xn: Tn): Y = body
不是
的语法糖val f = (x1: T1, ..., xn: Tn): Y => body
前者是一种方法,后者是类型FunctionN[T1, ..., Tn, Y]
的值。虽然这两个定义在受ML影响的其他语言中可能会以相同的方式处理,但在Scala中并非如此。 Scala区分方法和函数。
答案 1 :(得分:2)
特征Aaa
定义 方法 a
,但类Bbb
定义 函数值 a
。方法与函数值不同是Scala,因此类a
中Bbb
的定义未实现a
中的Aaa
。由于Aaa.a
没有定义,因此必须将类声明为abstract
。
如果您这样做,它将起作用:
class Bbb extends Aaa {
def a(x:Int) = x == 42
}
如果你真的需要一个函数值而不是一个方法,你需要声明另一个val
并使用 eta-expansion ,如下所示:
class Bbb extends Aaa {
def a(x:Int) = x == 42
val b = a _
}
b
现在可以作为函数参数传递给filter
等调用,而a
则不能。