为什么 Scala 的不可变 Set 在其类型上不是协变的?
-
21-08-2019 - |
题
编辑: :根据原来的答案重写这个问题
这 scala.collection.immutable.Set
类的类型参数不是协变的。为什么是这样?
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
是因为后面集作为函数的概念在其类型参数是不变的。下列签名应当澄清的事情略有:
trait Set[A] extends (A=>Boolean) {
def apply(e: A): Boolean
}
如果Set
是在A
协变,所述apply
方法将不能取类型A
的参数由于功能的逆变。 Set
可能是的逆变的在A
,但是当你想要做这样的事情这也导致问题:
def elements: Iterable[A]
总之,最佳解决方案是保持不变的事情,即使是不可变的数据结构。你会发现,immutable.Map
也不变其类型参数之一。
其他提示
在 http://www.scala-lang.org/node/9764 马丁·奥德斯基写道:
“关于套的问题,我相信非方差从实现还茎。公共集实现为哈希表,这是关键类型的非变体数组。我同意这是一个有点恼人的不规则性。”
所以,似乎我们所有的努力,构建一个原则性的原因被误导的: - )
编辑: :对于任何想知道为什么这个答案似乎有点偏离主题的人来说,这是因为我(提问者)修改了问题。
Scala 的类型推断足以确定在某些情况下您需要 CharSequences 而不是 Strings。特别是,以下内容在 2.7.3 中对我有用:
import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
至于如何直接创建immutable.HashSets:不。作为实现优化,少于 5 个元素的 immutable.HashSet 实际上并不是 immutable.HashSet 的实例。它们是 EmptySet、Set1、Set2、Set3 或 Set4。这些类是 immutable.Set 的子类,但不是 immutable.HashSet 的子类。
不隶属于 StackOverflow