在示例 1 中,+A
is 不是对 A 的约束。任何类型都可以是 Foo 的参数。它是对 的约束Foo
。表示在 的接口中Foo
,A
只能出现在协变的位置(简而言之,可能是方法结果,而不是方法参数)。
Bar
没有协变意味着 Bar 的接口不满足相同的约束(或者至少不宣传它),所以可能在 中,添加了一个带参数Bar
的方法。A
这很常见。例如,有collection.Seq[+A]
,它由 扩展collection.mutable.Seq[A]
。这不会造成不健全的问题。如果Y <: X
, aBar[Y]
不是 a Bar[X]
,但它仍然是 a Foo[X]
。
另一方面,在示例 2 中,A[+_]
是对 的约束A
。只有具有协变类型参数的类型才可以是 Foo 的参数。的代码Foo
可能会利用该约束,例如将 分配A[String]
给A[Any]
的代码中的某处Foo
。
然后允许Bar
用非协变类型实例化是不合理的。继承自的代码Foo
仍然可以被调用并将 分配A[String]
给A[Any]
, whenA
不再是协变的。
只要您允许解除对通用参数的约束,就会发生非常相似的可靠性问题。假设你有Foo[X <: Ordered[X]]
(或Foo[X : ordering]
)并且你有一个方法sort
在Foo
. 假设那Bar[X] extends Foo
是允许的。Bar
可能需要订购的代码中没有任何内容X
,但仍然sort
可以调用,并且肯定会与无法订购的项目行为不端。
关于您在 Traversable[+Elem, +Col[+_]] 的评论中的问题,并将其扩展为创建一个可变类:
从技术上讲,是的,你可以扩展它并var youCanMutateThat : Elem = _
在里面放一些。我想这不是你要找的。但我想你的计划是允许使用带有可变 Col 的扩展,我认为你不能这样做,原因如上所述。但是,为什么你首先有 Col[+_] 约束?