类型模式匹配为什么必须变量

Jac*_* P. 2 expression scala pattern-matching generic-programming

我正在阅读“第2部分急躁的scala”第14.4节,对上下文感到困惑:

您可以匹配表达式的类型,例如:

obj match {
   case x:Int => x
   case s:String => Integer.parseInt(s)
   case _:BigInt => Int.MaxValue
   case _ => 0
}
Run Code Online (Sandbox Code Playgroud)

与类型匹配时,必须提供变量名称。否则,您匹配对象:

obj match {
   case _:BigInt => Int.MaxValue // Matches any object of type BigInt
   case BigInt => -1 // Matches the BigInt object of type Class
}
Run Code Online (Sandbox Code Playgroud)

我很困惑的是,如果我进行如下测试,那么如何理解obj哪个请求是expression

val x = 121
val obj : Any = x
obj == 121 // true

obj match {
   case x:Int => x
   case s:String => Integer.parseInt(s)
   case _:BigInt => Int.MaxValue
   case _ => 0
} // res133: Int = 121

Run Code Online (Sandbox Code Playgroud)

但是,如果我只是将Integer值赋给obj,则编译器将引发错误:

val obj2 = 121
obj2 == 121 // true

obj2 match {
   case x:Int => x
   case s:String => Integer.parseInt(s)
   case _:BigInt => Int.MaxValue
   case _ => 0
} // <console>:22: error : scrutinee is incompatible with pattern type;
found : String
required : Int
    case s : String => Integer.parseInt(s)
             ^    
<console>:23: error : scrutinee is incompatible with pattern type;
found : BigInt
required : Int
    case _ : BigInt => Int.MaxValue
             ^      
Run Code Online (Sandbox Code Playgroud)

唯一的区别是前一个示例obj由另一个变量分配,而后一个示例obj由Integer值分配。为什么后面的示例会出现编译错误?

问题更新:我知道“编译器知道那obj2Int”,但是,我认为这是match表达式的工作原理,即因为obj2Int并且它遇到了第一个match子句,case x:Int => x所以匹配成功了,整个匹配表达式完成了。我认为这应该与前面的示例完全相同,唯一的区别是这两个变量是AnyInt类型的,但是它们都与第一个match子句匹配,并且都应正确编译。

从本书的第14.4节“在Scala中,这种(类型模式)匹配优于使用isInstanceOf运算符”,我认为使用类型模式是一种识别对象类型的方法。如果我们知道对象类型,“类型模式”用于什么?

第二个问题是我很困惑下面的上下文。如何理解“ BigInt类型的对象”与“ Class类型的BigInt对象”?“类型Class”与java泛型/反射概念有关吗?

obj match {
   case _:BigInt => Int.MaxValue // Matches any object of type BigInt
   case BigInt => -1 // Matches the BigInt object of type Class
}
Run Code Online (Sandbox Code Playgroud)

谢谢 !

Tim*_*Tim 5

在第二种情况下,编译器知道obj2Int,因此知道不可能成功匹配StringBigInt成功匹配。


在编译时已知与运行时已知之间存在区别。您有以下代码:

val x = 121
val obj: Any = x
Run Code Online (Sandbox Code Playgroud)

在运行时,x和和objInt将匹配match表达式中的第一种情况。

在编译时,编译器知道xInt这样,因此知道测试String或没有任何意义BigInt。所有它所知道的obj是,它是Any那么这是确定检查StringBigInt或任何其他类型。

现在,在这种情况下,很显然的是,编译器可以制定出obj实际上是Int,但是这是不可能在一般情况下。编译器没有使用关于类型推断的复杂规则,而只是使用程序员为值赋予的类型Any。因此,它假定obj可能是这样StringBigInt即使在这种情况下,从代码中也可以看出来不是。