为什么在构造函数中的 Scala var 中的协变类是被禁止的?



I have class

class GenericClass[+T] (var x: T) {}

当我尝试编译它时,我得到:

Error:(6, 33) covariant type T occurs in contravariant position in type T of value x_=
class GenericCellImm[+T] (var x: T) {

如何解决?问题原因是什么?

协变泛型类型意味着如果你有类Base和扩展BaseChild,那么在GenericClass[Base]是正确类型的每个上下文中,使用类型为GenericClass[Child]的对象也将是正确的。粗略地近似,这意味着如果您的GenericClass[T]提供只读 API,您可以进行+T协变,因为返回Child而不是Base始终是安全的。但是,如果您的GenericClass[T]中有一些可写的 API,则情况并非如此。请考虑以下代码:

def writeDefault(gc: GenericClass[Base]):Unit = {
gc.x = new Base()
}

如果gc确实属于GenericClass[Base]类型,则此代码是安全的,但如果GenericClass[Child],则会将类型为Base的值写入键入Child的字段,这会破坏预期的类型安全性。考虑

class Base(){}
class Child(childField:Int) extends Base {}
def bad():Unit = {
val gc = new GenericClass[new Child(1)]
writeDefault(gc)
println(gc.childField) // Oops! there is no childField in Base
}

这正是编译器不允许您的代码具有协方差的原因。

如果你想得到一些关于如何解决它的真正建议,你应该描述你试图解决的更高层次的问题。如果没有这样的描述,真的很难猜测是否只需要使用val而不是var来,或者你只需要完全消除协方差,或者你是否需要更复杂的代码。

最新更新