Scala 之旅

类型推断

语言

Scala 编译器通常可以推断表达式的类型,因此你不必显式声明它。

省略类型

val businessName = "Montreux Jazz Café"

编译器可以检测到 businessName 是一个字符串。它对方法的工作方式类似

def squareOf(x: Int) = x * x

编译器可以推断出返回类型是 Int,因此不需要显式的返回类型。

对于递归方法,编译器无法推断结果类型。这是一个程序,它将因此导致编译器失败

def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1)
def fac(n: Int) = if n == 0 then 1 else n * fac(n - 1)

当调用 多态方法 或实例化 泛型类 时,指定类型参数也不是强制性的。Scala 编译器将从上下文和实际方法/构造函数参数的类型中推断出此类缺少的类型参数。

这里有两个示例

case class MyPair[A, B](x: A, y: B)
val p = MyPair(1, "scala") // type: MyPair[Int, String]

def id[T](x: T) = x
val q = id(1)              // type: Int

编译器使用 MyPair 的参数类型来确定 AB 的类型。同样适用于 x 的类型。

参数

编译器从不推断方法参数类型。但是,在某些情况下,当函数作为参数传递时,它可以推断匿名函数参数类型。

Seq(1, 3, 4).map(x => x * 2)  // List(2, 6, 8)

映射的参数是 f: A => B。因为我们在 Seq 中放置了整数,所以编译器知道 AInt(即 x 是一个整数)。因此,编译器可以从 x * 2 推断出 B 是类型 Int

依赖类型推断的情况

通常认为在公开 API 中声明公开成员的类型更具可读性。因此,我们建议你为将公开给代码用户的任何 API 明确指定类型。

此外,类型推断有时会推断出过于具体的类型。假设我们编写

var obj = null

然后我们无法继续进行此重新赋值

obj = new AnyRef

它不会编译,因为为 obj 推断的类型是 Null。由于该类型的唯一值是 null,因此无法分配不同的值。

本页的贡献者