我正在阅读“Scala for Impatient 2nd”第 14.4 节,我对上下文感到困惑:
You can match on the type of an expression, for example :
obj match {
case x:Int => x
case s:String => Integer.parseInt(s)
case _:BigInt => Int.MaxValue
case _ => 0
}
When you match against a type, you must supply a variable name. Otherwise, you match the object :
obj match {
case _:BigInt => Int.MaxValue // Matches any object of type BigInt
case BigInt => -1 // Matches the BigInt object of type Class
}
我感到困惑的是如何理解作为 expression
请求的 obj
:
如果我测试如下:
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
但是,如果我只是将整数值分配给 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
^
唯一的区别是前一个例子我给 obj
分配了另一个变量,而后一个例子我给 obj
分配了一个 Integer 值。为什么后一个例子会出现编译错误?
问题更新:我知道“编译器知道 obj2
是 Int
”,但是,我认为那是 匹配的
表达式适用于,i,e 因为 obj2
是 Int
并且它满足第一个 match
子句 case x:Int => x
这样匹配成功,整个匹配表达式就完成了。我想这应该和前面的例子一模一样,唯一不同的是这两个变量是Any
和Int
类型,但是都匹配到了第一个match子句并且它们都应该被正确编译。
从本书第 14.4 节“在 Scala 中,这种(类型模式)匹配优于使用 isInstanceOf
运算符”,我认为使用类型模式是识别对象类型的一种方式。如果我们知道对象类型,那么“类型模式”有什么用?
第二个问题是我对下面的上下文感到困惑。如何理解“BigInt 类型的对象”与“Class 类型的 BigInt 对象”? “type Class
”与 java generic/reflection 概念相关吗?
obj match {
case _:BigInt => Int.MaxValue // Matches any object of type BigInt
case BigInt => -1 // Matches the BigInt object of type Class
}
谢谢!
最佳答案
在第二种情况下,编译器知道 obj2
是 Int
,因此它知道不可能匹配 String
或BigInt
可以成功。
编译时已知的和运行时已知的之间存在区别。您有以下代码:
val x = 121
val obj: Any = x
在运行时,x
和 obj
都是 Int
并且将匹配您的 match
中的第一个 case表达。
在编译时,编译器知道 x
是 Int
,因此它知道没有必要测试 String
或 大整数
。它对 obj
的所有了解是它是 Any
因此可以检查 String
、BigInt
或任何其他类型。
现在在这种情况下,很明显编译器可以计算出 obj
实际上是 Int
,但在一般情况下这是不可能的。编译器没有关于类型推断的复杂规则,而是使用程序员赋予值的类型,即 Any
。因此它假定 obj
可以是 String
或 BigInt
,即使在这种情况下从代码中可以明显看出它不是。
关于scala - 类型模式匹配为什么变量是必须的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56897884/