那么例如为什么List(1,2,3,4).contains("wtf")
还要编译呢?如果编译器拒绝这个不是很好吗?
3 回答
很多有趣的答案,但这是我自己的理论:如果contains
没有收到Any
,则Seq
不能是协变的。
例如,请参阅 ,Set
它不是协变的,并且contains
采用 anA
而不是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 ==)
^
“包含”基本上是关于相等性测试,Scala 中的相等性(如在它之前的 Java 中)是无类型的。具有无类型相等的实用价值很小,但不为零。例如,在某些情况下,不同类的两个对象彼此相等是有意义的。例如,如果 RGBColor 类型的对象定义相同的色调,您可能希望它们与 PantoneColor 相等,或者如果它们包含相同的元素,则不可变的 HashSet 和不可变的 TreeSet 相等。也就是说,无类型平等也引起了很多麻烦,编译器可以很容易地捕捉到这一点List(1,2,3,4).contains("wtf")
是荒谬的,但不会是其中之一。
大多数 Java 错误查找工具都包含用于检测不可能的非类型化相等使用的测试。(我在 IntelliJ IDEA 中编写了检查来执行此操作。)毫无疑问,当 Scala 错误查找工具上线时,这些将是最先检测到的错误之一。
SeqLike.contains 通过检查序列中等于值的元素(使用 ==)来检查值是否存在。== 需要一个 Any 所以我怀疑这就是原因。