问题描述
@uncheckedVariance
可用于弥合 Scala 的声明站点差异注释和 Java 的不变泛型之间的差距.
@uncheckedVariance
can be used to bridge the gap between Scala's declaration site variance annotations and Java's invariant generics.
scala> import java.util.Comparator
import java.util.Comparator
scala> trait Foo[T] extends Comparator[T]
defined trait Foo
scala> trait Foo[-T] extends Comparator[T]
<console>:5: error: contravariant type T occurs in invariant position in type [-T]java.lang.Object with java.util.Comparator[T] of trait Foo
trait Foo[-T] extends Comparator[T]
^
scala> import annotation.unchecked._
import annotation.unchecked._
scala> trait Foo[-T] extends Comparator[T @uncheckedVariance]
defined trait Foo
这说明 java.util.Comparator 自然是逆变的,即类型参数 T
出现在参数中,从不出现在返回类型中.
This says that java.util.Comparator is naturally contra-variant, that is the type parameter T
appears in parameters and never in a return type.
这就提出了一个问题:为什么它也用于不从 Java 接口扩展的 Scala 集合库中?
This raises the question: why is it also used in the Scala collections library which doesn't extends from Java interfaces?
trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]] extends HasNewBuilder[A, CC[A] @uncheckedVariance]
此注释的有效用途是什么?
What are the valid uses for this annotation?
推荐答案
问题是 GenericTraversableTemplate 被使用了两次:一次用于可变集合(其类型参数应该是不变的),一次用于不可变集合(其中协方差不变)国王).
The problem is that GenericTraversableTemplate is used twice: once for mutable collections (where its type parameter should be invariant), and once for immutable collections (where covariance is invariably king).
GenericTraversableTemplate 的类型检查假设 A 类型参数具有协方差或不变性.但是,当我们以可变特征继承它时,我们必须选择不变性.相反,我们希望在不可变子类中具有协方差.
GenericTraversableTemplate's typechecks assuming either covariance or invariance for the A type parameter. However, when we inherit it in a mutable trait, we have to pick invariance. Conversely, we'd like covariance in an immutable subclass.
由于我们无法抽象 GenericTraversableTemplate 中的方差注释(还 ;-)),因此我们可以根据子类将其实例化为其中之一,因此我们不得不求助于强制转换(@uncheckVariance 本质上是一种-投掷).为了进一步阅读,我推荐我的论文(对不起;-))或我们最近的比特纸
Since we can't abstract over the variance annotation (yet ;-)) in GenericTraversableTemplate, so that we could have instantiated it to either one depending on the subclass, we have to resort to casting (@uncheckVariance is essentially a kind-cast). For further reading, I recommend my dissertation (sorry ;-)) or our recent bitrot paper
这篇关于Scala 中何时需要 @uncheckedVariance,为什么在 GenericTraversableTemplate 中使用它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!