我知道这个问题以前已经被问过了,但是要么答案不适用于这种情况,要么我不理解它们。
基本上,为什么下面这个(重新创建我的问题的简单示例)不起作用?
class Test[+T] {
var list: List[T] = _
}
我遇到的问题是,我有一个对象,想要传入一个
Test[Nothing]
实例(空的 Test
),但是除非我将 T
中的 Test
协变,否则无法实现此操作。我知道这个问题以前已经被问过了,但是要么答案不适用于这种情况,要么我不理解它们。
基本上,为什么下面这个(重新创建我的问题的简单示例)不起作用?
class Test[+T] {
var list: List[T] = _
}
Test[Nothing]
实例(空的 Test
),但是除非我将 T
中的 Test
协变,否则无法实现此操作。T
中的测试协变意味着对于任何 A
,Test[A]
都是 Test[Any]
的子类型。因此让我们创建一个 Test
:val test_string = new Test[String]
Test[String]
,其中包含的list
类型是List[String]
。Test[String]
是Test[Any]
的子类型,因此应该允许以下操作:val test_any : Test[Any] = test_string
现在,我们有一个Test[Any]
,因此test_any.list
是类型List[Any]
,这意味着以下内容应该是有效的:
test_any.list = List[Any]()
List[Any]
分配给了 test_strings 列表成员,这是不允许的,因为它应该是一个 List[String]
,而不是一个 List[Any]
。这也意味着你可以在列表中添加任何内容,因为它是类型 List[Any]
。
list
定义为val
:class Test[+T](val list: List[T])
,但这取决于何时初始化列表,可能并不总是可行的选择。 - Malte Schwerhofflist
定义为var
时,编译器会自动提供改变方法def list_=(l: List[T]): Unit
。在这个方法中,T
类型参数不在协变位置。如果你尝试将T
设为逆变,由于相应的访问方法,情况也会发生类似的情况。除了将T
设置为非变或使用一个val
来定义你的列表之外,没有其他解决办法。 - pagoda_5b