嵌套收藏中的选项的奇怪类型擦除



在嵌套集合中使用选项时,我遇到了以下奇怪的问题:

val works: Array[Option[Int]] = Array(1)
  .map { t => Some(t)}
val fails: Array[Array[Option[Int]]] = Array(Array(1))
  .map { ts => ts.map { Some(_)} }
// error: type mismatch;  found   : Array[Array[Some[Int]]] required: Array[Array[Option[Int]]]
val worksButUgly: Array[Array[Option[Int]]] = Array(Array(1))
  .map { ts => ts.map { case t => (Some(t).asInstanceOf[Option[Int]])}}

我想这可能是某种类型擦除的问题,但这是 Scala 中的预期行为吗?有谁知道到底发生了什么?

Scala 中的数组是不变的。这可以防止数组在例如Java中出现的一些问题,您可以在Java中创建某个东西的数组,声明它是某物的超类数组,然后放入另一个子类。例如,说苹果数组是水果数组,然后放入香蕉。最糟糕的是它在运行时失败,而不是在编译时失败。

出于这个原因,Scala决定数组应该是不变的。这意味着Array[Apple]不是Array[Fruit]的子类。(请注意,与数组不同,不可变集合通常是协变的,例如 List,因为不变性阻止我们以后将任何香蕉放入其中)

所以是的。 SomeOption的子类,但Array[Some]不是Array[Option]的子类。这些将起作用:

val foo1: Array[Array[Option[Int]]] = Array(Array(1))
  .map { ts => ts.map { Option(_)} }
val foo2: Array[List[Option[Int]]] = Array(List(1))
  .map { ts => ts.map { Some(_)} }

使用 Some(t): Option[Int] 而不是 Some(t).asInstanceOf[Option[Int]] 。它既短又安全:如果类型不匹配,它将无法编译。

最新更新