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值分配。为什么后面的示例会出现编译错误?
问题更新:我知道“编译器知道那obj2是Int”,但是,我认为这是match表达式的工作原理,即因为obj2是Int并且它遇到了第一个match子句,case x:Int => x所以匹配成功了,整个匹配表达式完成了。我认为这应该与前面的示例完全相同,唯一的区别是这两个变量是Any和Int类型的,但是它们都与第一个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)
谢谢 !
在第二种情况下,编译器知道obj2是Int,因此知道不可能成功匹配String或BigInt成功匹配。
在编译时已知与运行时已知之间存在区别。您有以下代码:
val x = 121
val obj: Any = x
Run Code Online (Sandbox Code Playgroud)
在运行时,x和和obj都Int将匹配match表达式中的第一种情况。
在编译时,编译器知道x是Int这样,因此知道测试String或没有任何意义BigInt。所有它所知道的obj是,它是Any那么这是确定检查String,BigInt或任何其他类型。
现在,在这种情况下,很显然的是,编译器可以制定出obj实际上是Int,但是这是不可能在一般情况下。编译器没有使用关于类型推断的复杂规则,而只是使用程序员为值赋予的类型Any。因此,它假定obj可能是这样String,BigInt即使在这种情况下,从代码中也可以看出来不是。