协变型T出现在逆变位置

mon*_*ack 18 scala

我知道之前已经问过这个问题,但是答案不适用于这种情况,或者我不理解它们.

基本上,为什么以下(重新创建我的问题的简单示例)不起作用?

class Test[+T] {
    var list: List[T] = _
}
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是我有一个对象,我想传递一个Test [Nothing]的实例(空的测试),除非我在T中使用Test co-variant,否则这不起作用.

ste*_*tew 26

使得在测试协变T装置,其Test[A]是的子类型Test[Any]为任何A.所以让我们创建一个Test:

val test_string = new Test[String]
Run Code Online (Sandbox Code Playgroud)

现在我们有一个Test[String]和包含list的类型List[String].

由于Test[String]是子类型Test[Any],因此应允许以下内容:

val test_any : Test[Any] = test_string
Run Code Online (Sandbox Code Playgroud)

现在,我们有一个Test[Any],因此test_any.list是类型List[Any],这意味着以下应该是有效的:

test_any.list = List[Any]()
Run Code Online (Sandbox Code Playgroud)

这意味着我们只是List[Any]为test_strings列表成员分配了一个,不应该被允许,因为它应该是a List[String],而不是a List[Any].这也意味着你可以在列表中添加任何内容,因为它是类型List[Any].

  • 这里的具体问题是将`list`定义为`var`,编译器会自动提供mutator方法`def list _ =(l:List [T]):Unit`,在这个方法中,`T`类型参数不是在*协变*位置.如果您尝试将`T`设置为*contravariant*,则会发生相同的情况,因为相应的存取方法.除了将`T`设置为*nonvariant*或使用`val`作为列表之外,没有其他解决方法. (11认同)