我正在阅读“ Scala for Im耐心第二版”第14.4节,其中我对上下文感到困惑:
您可以匹配表达式的类型,例如:
obj match {
case x:Int => x
case s:String => Integer.parseInt(s)
case _:BigInt => Int.MaxValue
case _ => 0
}
与类型匹配时,必须提供变量名称。 否则,您将匹配对象:
obj match {
case _:BigInt => Int.MaxValue // Matches any object of type BigInt
case BigInt => -1 // Matches the BigInt object of type Class
}
我很困惑的是如何理解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
但是,如果我只是将整数值分配给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
。为什么后面的示例会出现编译错误?
问题更新:我知道“编译器知道obj2
是Int
”,但是,我认为这是match
表达式的作用,我,e因为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
}
谢谢!
答案 0 :(得分:5)
在第二种情况下,编译器知道obj2
是Int
,因此,它知道不可能成功匹配String
或BigInt
。 / p>
在编译时已知与运行时已知之间有区别。您具有以下代码:
val x = 121
val obj: Any = x
在运行时,x
和obj
均为Int
,并且将与match
表达式中的第一种情况匹配。
在编译时,编译器知道x
是Int
,因此知道测试String
或BigInt
没有意义。关于obj
的所有知识就是它是Any
,因此可以检查String
,BigInt
或任何其他类型。
现在在这种情况下,很明显编译器可以算出obj
实际上是Int
,但是在一般情况下是不可能的。编译器没有使用关于类型推断的复杂规则,而只是使用程序员赋予值Any
的类型。因此,它假定obj
可以是String
或BigInt
,即使在这种情况下,从代码中也可以看出并非如此。
答案 1 :(得分:3)
如何理解“ BigInt类型的对象”与“ Class类型的BigInt对象”? “类型类”与java泛型/反射概念有关吗?
这只是书中的错误。 BigInt
模式(即case BigInt => ...
)与声明为
object BigInt { ... }
用代码表示。它不是Class
类型的 not ;类型为is written as BigInt.type
,但很少使用。
所以如果你写
val x: Any = BigInt
x match {
case _: BigInt => // doesn't match
case BigInt => // matches
}
而val x: Any = new BigInt(...)
将匹配第一个而不是第二个。
答案 2 :(得分:1)
第二项分配缺少类型说明,因此由于类型推断
val obj2 = 121
将obj2
设为Int
,而不是
val obj : Any = x
这使它成为Any
。