Scala似乎在提取过程中对常规值赋值与赋值具有不同的语义。这为我创建了一些非常微妙的运行时错误,因为我的代码库随着时间的推移而迁移。
举例说明:
case class Foo(s: String)
def anyRef(): AnyRef = { ... }
val Foo(x) = anyRef() // compiles but throws exception if anyRef() is not a Foo
val f: Foo = anyRef() // does not compile
我不明白为什么两个val
赋值行在编译/运行时行为方面会失衡。
有些我很好奇:这种行为有原因吗?它是否是实现提取方式的不良后果?
(在Scala 2.11.7中测试)
答案 0 :(得分:2)
是的,有。
如果是提取器,则指定您希望在此位置匹配的模式。这被转换为从Any到Option [String]的一个提取器方法的调用,并且可以使用您提供的AnyRef类型的值调用此方法。你只是断言,你确实得到了一个结果而不是“无”。
在另一行中,您使用的是类型注释,即您明确指定了“f”的类型。但是你要分配一个不兼容的值。
当然编译器可以添加隐式类型转换,但是使类型转换变得如此简单并不适合像Scala这样的语言。
您还应该记住,提取器与类型无关。在模式Foo(x)
中,名称Foo与Foo类型无关。它只是一个提取器方法的名称。
以这种方式使用模式当然是一个非常动态的功能,但我认为这是故意的。