首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala Set[_]对Set[Any]

Scala Set[_]对Set[Any]
EN

Stack Overflow用户
提问于 2015-03-04 23:12:46
回答 1查看 454关注 0票数 5

我有以下代码:

代码语言:javascript
复制
case set: Set[Any] => setFormat[Any].write(set)

但是,编译器发出警告:

类型模式scala.collection.SetAny中的任何非变量类型参数都是不检查的,因为它是通过擦除警告消除的。

当然可以。

所以我把我的台词改为:

代码语言:javascript
复制
case set: Set[_] => setFormat[Any].write(set)

现在我得到了一个错误:

错误发现: scala.collection.Set_必需: scala.collection.SetAny

Q1.这两者有什么区别?

然后,我将代码更改为:

代码语言:javascript
复制
case set: Set[_] => setFormat[Any].write(set.map(s => s))

现在,它很高兴没有任何错误或警告。

Q2.为什么这样做??

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-05 00:11:35

Q1Set[Any]是元素类型为Any的集合。Set[_]是一个元素类型未知的集合。也许是Set[Int],可能是Set[String],也许是Set[Any]。与大多数(不可变)集合相反,Set不是协变量(声明是trait Set[A],而不是trait Set[+A])。因此,Set[String]并不是Set[Any],而且更普遍地说,您不能保证其元素类型(即Set[_])是Set[Any]

Q2:它的工作原理是,无论集合元素的(未知)类型A是什么,恒等函数s => s都可以看作是一个函数A => Any。(方差为Function1[-T1, +R]。然后,根据需要,可以将结果set.map(s => s)键入为Set[Any]

备注:如果没有setFormat和with的定义,很难确定,但是您真的需要在setFormat[Any]中明确使用[Any]类型参数吗?可以将存在主义传递给泛型函数,即

代码语言:javascript
复制
val x: X[_] = ....
def f[A](xa: X[A]) = ...
f(x) // allowed

但是不允许在调用站点(例如f[Any](x))中显式显示,因为我们不知道X是否是X[Any]

注意:关于Set不是协变的:这是不幸的,因为人们觉得一组猫也是一组动物。这有一个原因(可能还有其他原因)。

Set有一个方法def contains(a: A): Boolean,此签名防止协方差。其他集合有一个def contains[A1 >: A](a: A): Boolean,它允许协方差,但实际上等同于def contains(a: Any): Boolean

它可以工作,因为实现是基于方法equals的,它随处可用(随JVM一起提供),并且采用Any类型的参数。使用与列表内容无关的类型的值进行调用很可能是错误的,更有约束的签名会更好,但这是为协方差付出的小代价。

但是,contains的轻松签名限制了基于equals (可能还有hashCode )的实现。它不适用于基于排序的实现,后者不接受非类型化的参数。禁止这种(非常常见的)集合实现可能会被视为协方差的代价过高。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28866944

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档