为什么Scala的不可变集合在它的types中不是协变的?
编辑 :根据原来的答案重新写这个问题
scala.collection.immutable.Set
类在其types参数中不是协变的。 为什么是这样?
import scala.collection.immutable._ def foo(s: Set[CharSequence]): Unit = { println(s) } def bar(): Unit = { val s: Set[String] = Set("Hello", "World"); foo(s); //DOES NOT COMPILE, regardless of whether type is declared //explicitly in the val s declaration }
由于设置为函数的概念,set的types参数是不变的。 以下签名应该略微澄清一些事情:
trait Set[A] extends (A=>Boolean) { def apply(e: A): Boolean }
如果Set
在A
是协变A
,则由于函数的变换, apply
方法将不能取A
types的参数。 A
可能在A
是可逆 A
,但是当你想要做这样的事情时,这也会导致问题:
def elements: Iterable[A]
总之,最好的解决scheme是保持事物不变,即使对于不可变的数据结构。 你会注意到immutable.Map
在其types参数中也是不变的。
在http://www.scala-lang.org/node/9764 Martin Odersky写道:
“关于集合的问题,我相信这种非变异也来自于实现,通用集合是作为哈希表来实现的,哈希表是关键types的非variables数组,我同意这是一个有点烦人的不规则性。
所以,我们所有为此构build原则性理由的努力都被误导了:-)
编辑 :任何人想知道为什么这个答案似乎有点离题,这是因为我(提问者)已经修改了这个问题。
Scala的types推断足以certificate在某些情况下你需要CharSequences而不是Strings。 特别是,下面的2.7.3中为我工作:
import scala.collections.immutable._ def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
至于如何直接创buildimmutable.HashSets:不。 作为一个实现优化,less于5个元素的immutable.HashSets实际上并不是immutable.HashSet的实例。 它们是EmptySet,Set1,Set2,Set3或Set4。 这些类是不可变的。设置,但不是immutable.HashSet。