作为尝试理解scala的差异和相似之处的一部分,我试图理解Java“Object”类型的等价物。
如果我有一个Scala列表List [TYPE],那么Type必须支持以下任何一项 Int,Any,(Int,Any))。
注意:我理解这是一种糟糕的(可怕的)编程技术,但它有助于我理解。
我最初认为List [Any]会起作用,但无法让它适用于所有情况:
[error] found : org.apache.spark.rdd.RDD[Any]
[error] required: org.apache.spark.rdd.RDD[(Any, ?)]
类似地
[error] found : org.apache.spark.rdd.RDD[(Any, (Any, Any))] [error] required: org.apache.spark.rdd.RDD[Any] [error] Note: (Any, (Any, Any)) <: Any, but class RDD is invariant in type T.
如果Any是一种超级类型的东西,为什么在这里提到不变量?
答案 0 :(得分:3)
你是Any
是Scala中所有类型的超类型。
错误消息是由不同的问题引起的。
[error] found : org.apache.spark.rdd.RDD[Any]
[error] required: org.apache.spark.rdd.RDD[(Any, ?)]
在这种情况下,您具有超类型的混合子类型。该错误表明您已使用Any
而不是(Any, ?)
,只允许使用其他方式。
[error] found : org.apache.spark.rdd.RDD[(Any, (Any, Any))] [error] required: org.apache.spark.rdd.RDD[Any] [error] Note: (Any, (Any, Any)) <: Any, but class RDD is invariant in type T.
这里的问题是多态和方差注释。如果类型变量是不变的(既不是协变也不是逆变),则类型必须是完全匹配。您不能使用子类型或超级类型。
要允许第二个用例,RDD
中的type参数应该是协变的。 Scala中的协方差使用+
注释(例如class RDD[+T]
)。
协方差意味着如果类型A
是B
的子类型且Foo
在其第一个类型参数中是协变的,则Foo[A]
是子类型Foo[B]
。
Scala <:
用于描述类型之间的顺序(子/超类型关系)。
(Any, (Any, Any)) <: Any
表示(Any, (Any, Any))
是Any
的子类型,但RDD
不是协变的,因此RDD[(Any, (Any, Any))] <: RDD[Any]
是错误的。
答案 1 :(得分:2)
您可以使用scala控制台和类型推断来检查您将拥有的类型:
scala> val list = List(1, (2, "String"), Array.empty[Byte])
list: List[Any] = List(1, (2,String), Array())
列表[任意]是正确的类型