Scala:为什么Seq.contains采用Any参数,而不是序列类型的参数?

时间:2010-09-09 17:28:42

标签: scala scala-collections

那么例如为什么List(1,2,3,4).contains("wtf")甚至可以编译?如果编译器拒绝了它会不会很好?

3 个答案:

答案 0 :(得分:20)

很多有趣的答案,但这是我自己的理论:如果contains没有收到Any,那么Seq就无法共变。

例如,请参阅Set,它不是共变体,其containsA而不是Any

其原因留给读者练习。 ;-)但这是一个提示:

scala> class Container[+A](elements: A*) {                         
     |   def contains(what: A): Boolean = elements exists (what ==)
     | }
<console>:7: error: covariant type A occurs in contravariant position in type A of value what
         def contains(what: A): Boolean = elements exists (what ==)
                      ^

答案 1 :(得分:4)

“contains”基本上是关于相等性测试的,并且Scala中的相等性(在之前的Java中)是无类型的。具有无类型相等性的实际价值很小,但不是零。例如,有几种情况下,不同类的两个对象彼此相等是有意义的。例如,您可能希望类型为RGBColor的对象等于PantoneColor(如果它们定义相同的色调),或者不可变的HashSet和不可变的TreeSet如果它们包含相同的元素则相等。也就是说,无类型相等也会引起一系列令人头疼的问题,编译器可以轻松捕获List(1,2,3,4).contains("wtf")这一事实是荒谬的,但不会是其中之一。

大多数Java错误查找工具都包含用于检测不可能的无类型相等使用的测试。 (我在IntelliJ IDEA中编写了这样的检查。)我毫不怀疑,当Scala错误查找工具上线时,这些将成为检测到的第一个错误。

答案 2 :(得分:1)

SeqLike.contains通过检查序列中等于该值的元素(使用==)来检查是否存在值。 ==接受Any,所以我怀疑这就是原因。