看看这个:
scala> class Container(val rows: Iterable[Iterable[Option[Any]]]) {}
defined class Container
scala> val row1 = Array(Some("test"),Some(1234))
row1: Array[Some[Any]] = Array(Some(test), Some(1234))
scala> val row2 = Array(Some("test2"), Some(12345))
row2: Array[Some[Any]] = Array(Some(test2), Some(12345))
scala> val listtest = List(row1, row2)
listtest: List[Array[Some[Any]]] = List(Array(Some(test), Some(1234)), Array(Some(test2), Some(12345)))
scala> val test = new Container(listtest)
<console>:11: error: type mismatch;
found : List[Array[Some[Any]]]
required: Iterable[Iterable[Option[Any]]]
val test = new Container(listtest)
^
scala> val test = new Container(List(row1,row2))
test: Container= Container@600a08
Run Code Online (Sandbox Code Playgroud)
如何定义Container的第二种方式,但第一种方式不适用?这些类型不一样吗?
Did*_*ont 13
这不是错误.Array是不协变的.B是B的子类型,不使Array [B]成为Array [A]的子类型.这与java相反,其中B []是A []的子类型,它是不健全的:
A[] b = new B[1];
b[0] = new (A);
-> ArrayStoreException
Run Code Online (Sandbox Code Playgroud)
所以你的数组[Some [Any]]不是数组[Option [Any]].您必须确保拥有可以使用的数组[选项]
val row2 = Array[Option[Any]](Some(test2), Some(12345))
Run Code Online (Sandbox Code Playgroud)
您还可以在其中一个项目上使用类型abscription:
val row2 = Array(Some(test2): Option[String], Some(12345))
Run Code Online (Sandbox Code Playgroud)
或者,如果您知道您的值为非null,
val row2 = Array(Option(test2), Option(12345))
Run Code Online (Sandbox Code Playgroud)
(这足以在其中一个值上做到这一点)
List另一方面,协变,这就是它的工作原因.
实际上很不幸的Some是,推断出更精确的类型,你想要将某种类型的东西称为Some(或None)而不是Option.
编辑对不起,看起来我完全错过了这一点,关于为何有不同.Array不是协变的,但是Iterable是.所以似乎Array[B]虽然不是一个Array[A],但应该是一个Iterable[A],那么一切都应该有效.如果Array是Iterable的子类型,那将是如此.它不是,它随JVM一起提供,无法扩展Iterable.有什么是隐式转换WrappedArray,这是一个Iterable.
写作时val l = List(row1, row2),没有理由应用此转换.它尽可能精确地键入列表.那么List是协变的事实(如果B是A,List [B]是List [A])当我们没有B是A时,它将不会启动,但是B有一个隐式转换为A.
另一方面,当您编写val l:List [Iterable [A]] = List(x,y)时,List(...)函数需要Iterable [A]参数,此时它会查找隐式转换.
仍然不是一个错误,但比我想象的更棘手.也许你可以做一个
class Container[T <% Iterable[Option[Any]]](val rows: Iterable[T])
Run Code Online (Sandbox Code Playgroud)