Scala 类型推断是怎么回事?怎么用?

文章导读
Previous Quiz Next Scala 编译器能够自动推断表达式的类型。因此,它减少了对显式类型注解的需求。类型推断表示,任何表达式的数据类型,如方法返回类型和参数类型,都可以被编译器自动理解。参数列表中的类型可以省略。因为 Scala 已经知道 functio
📋 目录
  1. 类型推断规则
  2. 函数中的类型推断
  3. 高阶函数中的类型推断
  4. 带有类型参数的高级类型推断
  5. 方法重载中的类型推断
  6. 隐式参数中的类型推断
  7. 模式匹配中的类型推断
  8. 类型推断总结
A A

Scala - 类型推断



Previous
Quiz
Next

Scala 编译器能够自动推断表达式的类型。因此,它减少了对显式类型注解的需求。类型推断表示,任何表达式的数据类型,如方法返回类型和参数类型,都可以被编译器自动理解。参数列表中的类型可以省略。因为 Scala 已经知道 functional interface 的单一抽象方法的预期参数类型。

在许多情况下,你可以忽略显式类型声明。因为 Scala 编译器可以根据上下文推断它们。例如,当你声明一个变量并初始化它时,编译器会从表达式的类型推断变量的类型。

以下示例展示了如何使用类型推断 -


val x = 42 

val y = x + 2.5 

类型推断规则

类型推断没有特定的语法。因为它依赖于编译器来推断类型。但它遵循以下规则 -

  • 变量和值声明 - 编译器从赋值的右侧推断类型。
  • 函数定义 - 编译器从函数体推断返回类型。
  • 方法调用 - 编译器根据用法推断方法参数和返回值类型。

示例

以下示例展示了如何使用类型推断来确定变量和函数返回类型 -

object Demo {
  def main(args: Array[String]): Unit = {
    
    val number = 10 
    
    
    val message = "Hello, Scala!" 

    
    def add(a: Int, b: Int) = a + b 

    
    val sum = add(number, 20) 
    
    println(s"Message: $message")
    println(s"Sum: $sum")
  }
}

将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。

命令

> scalac Demo.scala
> scala Demo

输出

在上述代码中,Scala 编译器根据赋的值推断变量 number 和 message 的类型。它还根据上下文推断 add 函数的返回类型以及变量 sum 的类型。

这将产生以下结果 -

Message: Hello, Scala!
Sum: 30

函数中的类型推断

类型推断用于函数定义。编译器可以根据函数体推断返回类型。

示例

以下示例展示了如何推断函数的返回类型 -

object Demo {
  def main(args: Array[String]): Unit = {
    def concatenate(str1: String, str2: String) = str1 + str2

    val result = concatenate("Scala ", "is awesome!")
    println(result) 
  }
}

将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。

命令

> scalac Demo.scala
> scala Demo

输出

在这个示例中,concatenate 函数没有显式的返回类型。Scala 编译器根据两个输入字符串的连接推断返回类型为 String。

这将产生以下结果 -

Scala is awesome!

高阶函数中的类型推断

你也可以在高阶函数中使用类型推断。这些函数将其他函数作为参数和/或将函数作为结果返回。

示例

以下示例展示了如何使用类型推断的高阶函数 -

object Demo {
  def main(args: Array[String]): Unit = {
    def applyFunction(f: Int => Int, value: Int) = f(value)

    val square = (x: Int) => x * x
    val result = applyFunction(square, 5)
    println(result) 
  }
}

将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。

命令

> scalac Demo.scala
> scala Demo

输出

在这个示例中,Scala 编译器为高阶函数 applyFunction 和 lambda 表达式 square 推断了类型。因此,代码简洁且易读,无需显式类型注解。

这将产生以下结果 -

25

带有类型参数的高级类型推断

你也可以将 Scala 类型推断扩展到泛型类和方法中的类型参数。

示例

以下示例展示了如何使用带有类型参数的泛型类 -

class Box[T](value: T) {
  def get: T = value
}

object Demo {
  def main(args: Array[String]): Unit = {
    // 编译器推断类型为 Box[Int]
    val intBox = new Box(42) 

    // 编译器推断类型为 Box[String]
    val stringBox = new Box("Scala") 
    
    println(intBox.get) 
    println(stringBox.get) 
  }
}

将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。

命令

> scalac Demo.scala
> scala Demo

输出

在这个示例中,Scala 编译器根据其初始化推断了 intBox stringBox 实例的类型。

这将产生以下结果 -

42
Scala

方法重载中的类型推断

你可以使用类型推断来管理方法重载。这样,正确的重载方法将根据参数的推断类型来选择。

示例

以下示例展示了如何使用类型推断进行方法重载 -

object Demo {
  def printValue(value: Int): Unit = println(s"Int value: $value")
  def printValue(value: String): Unit = println(s"String value: $value")

  def main(args: Array[String]): Unit = {
    val number = 100
    val text = "Hello, Scala"

    printValue(number) 
    printValue(text) 
  }
}

将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。

命令

> scalac Demo.scala
> scala Demo

输出

上述代码使用类型推断根据参数类型选择正确的方法重载。

这将产生以下结果 -

Int value: 100
String value: Hello, Scala

隐式参数中的类型推断

类型推断在使用隐式参数时也能很好地工作,从而在处理隐式值时获得更简洁且易读的代码。

示例

以下示例展示了如何使用隐式参数 -

object Demo {
  def main(args: Array[String]): Unit = {
    implicit val multiplier: Int = 2

    def multiply(value: Int)(implicit factor: Int): Int = value * factor

    val result = multiply(10)
    println(result) 
  }
}

将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。

命令

> scalac Demo.scala
> scala Demo

输出

上述代码使用隐式参数的类型推断将一个值乘以隐式因子。

这将产生以下结果 -

20

模式匹配中的类型推断

你可以在模式匹配中使用类型推断。编译器会推断匹配模式和表达式的类型。

示例

以下示例展示了如何进行模式匹配 -

object Demo {
  def main(args: Array[String]): Unit = {
    val value: Any = "Scala"

    value match {
      case s: String => println(s"String value: $s")
      case i: Int => println(s"Int value: $i")
      case _ => println("Unknown type")
    }
  }
}

将上述程序保存为 Demo.scala。使用以下命令编译并执行该程序。

命令

> scalac Demo.scala
> scala Demo

输出

上述代码使用模式匹配中的类型推断来确定匹配模式的类型。

这将产生以下结果 -

String value: Scala

类型推断总结

  • 类型推断减少了对显式类型注解的需求。
  • 类型推断可以推断变量、值、函数返回类型、方法参数等的类型。
  • 你可以在高阶函数、集合和模式匹配中使用类型推断。
  • 隐式参数会被推断,从而提供更简洁、可读的代码。