Generics 可遍历对象的继承和类型参数
我正在研究Scala 2.8集合类的源代码。我对scala.collection.Traversable的层次结构有疑问。请看以下声明:Generics 可遍历对象的继承和类型参数,generics,scala,scala-2.8,scala-collections,Generics,Scala,Scala 2.8,Scala Collections,我正在研究Scala 2.8集合类的源代码。我对scala.collection.Traversable的层次结构有疑问。请看以下声明: package scala.collection trait Traversable[+A] extends TraversableLike[A, Traversable[A]] with GenericTraversableTemplate[A, Traversable] trait Traversable
package scala.collection
trait Traversable[+A]
extends TraversableLike[A, Traversable[A]]
with GenericTraversableTemplate[A, Traversable]
trait TraversableLike[+A, +Repr]
extends HasNewBuilder[A, Repr]
with TraversableOnce[A]
package scala.collection.generic
trait HasNewBuilder[+A, +Repr]
trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]]
extends HasNewBuilder[A, CC[A] @uncheckedVariance]
我想在GenericTraversableTemplate
中使用@uncheckedVariance
注释也与此有关?(这似乎是一种潜在的不安全的黑客手段,用来迫使事情运转…)
编辑-在中找到了有关注释的一些有用答案(这是因为GenericTraversableTemplate
用于方差不同的可变集合和不可变集合)
问题:当您查看层次结构时,您会看到
Traversable
继承了HasNewBuilder
两次(一次通过TraversableLike
继承,一次通过GenericTraversableTemplate
),但类型参数略有不同。这到底是怎么回事?为什么不同的类型参数不会导致错误?原因是GenericTraversableTemplate
trait中的CC
参数。与具有种类*
(发音为“type”)的普通类型参数不同,此参数具有类型*=>*
(发音为“type to type”)。为了理解这意味着什么,您首先需要了解一些关于种类的背景知识
考虑以下代码段:
val a: Int = 42
这里我们看到42
,这是一个值。值具有内在类型。在本例中,我们的值是42
,类型是Int
。类型类似于包含许多值的类别。它表示变量a
可能的值。例如,我们知道a
不能包含值“foobar”
,因为该值的类型为字符串。因此,值有点像第一级抽象,而类型比值高一级
所以问题来了:是什么阻止了我们更进一步?如果值可以有类型,为什么类型上面不能有“某物”?那个“某物”被称为种类。种类是指类型,类型是指值,泛型类别限制了可以描述的类型
让我们看一些具体的例子:
type String
type Int
type List[Int]
这些是类型,它们都有种类*
。这是最常见的类型(这就是为什么我们称之为“类型”)。实际上,大多数类型都有这种类型。但是,有些人没有:
type List // note: compile error
这里我们有类型构造函数列表
,但这次我们“忘记”指定它的类型参数。事实证明,这实际上是一种类型,但却是另一种类型。具体来说,*=>*
。正如符号所暗示的,这种类型描述了一种类型,它将另一种类型的种类*
作为参数,从而产生一种新的种类*
。我们可以在第一个示例中看到这一点,其中我们将Int
类型(具有kind*
)传递给List
类型构造函数(具有kind*=>*
),生成类型List[Int]
(具有kind*
)
回到GenericTraversableTemplate
,让我们再次看看声明:
trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]]
请记住,List
属于*=>*
(这正是我们需要的CC
),但是List[Int]
具有种类*
,因此编译器拒绝它
对于记录,GenericTraversableTemplate
本身有一种,具体来说:(*x(*=>*)=>*)=>*
。这意味着GenericTraversableTemplate
是一种类型,它将两种类型作为参数——一种是*
,另一种是*=>*
——并产生一种类型的*
。在我们上面的示例中,GenericTraversableTemplate[String,List]
就是这样一种结果类型,正如我们计算的,它属于*
(它不需要参数)。感谢您花时间如此清晰地回答这个问题!我以前听说过“种类”,但直到现在才真正理解它们的含义。
trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]]
type GenericTraversableTemplate[String, List] // valid!
type GenericTraversableTemplate[String, List[Int]] // invalid!