在Scala 2.8中,为什么迭代器有一个contains方法,而Iterable没有?
我想在我的Iterables上调用“contains:-)我不知道为什么在在Scala 2.8中,为什么迭代器有一个contains方法,而Iterable没有?,scala,iterator,scala-2.8,scala-collections,Scala,Iterator,Scala 2.8,Scala Collections,我想在我的Iterables上调用“contains:-)我不知道为什么在Iterable或TraversableOnce上没有定义contains,但您可以自己轻松定义它: class TraversableWithContains[A](underlying: TraversableOnce[A]) { def contains(v: Any): Boolean = underlying.exists(_ == v) } implicit def addContains[A](i
Iterable
或TraversableOnce
上没有定义contains
,但您可以自己轻松定义它:
class TraversableWithContains[A](underlying: TraversableOnce[A]) {
def contains(v: Any): Boolean =
underlying.exists(_ == v)
}
implicit def addContains[A](i: Iterable[A]) = new TraversableWithContains(i)
并使用它,就好像它是在Iterable上定义的一样:
val iterable: Iterable[Int] = 1 to 4
assert(iterable.contains(3))
assert(!iterable.contains(5))
之所以
Iterable
没有contains
方法,是因为它的定义方式会对方差产生直接影响。基本上,有两种类型的签名对它有意义:
def contains(v: Any): Boolean
def contains(v: A): Boolean
第二个定义增加了类型安全性。但是,A
,它是集合的类型参数,显示在反变位置,强制集合保持不变。可以这样定义:
def contains[B >: A](v: B): Boolean
但是,与使用any
的第一个签名相比,这并不能提供任何改进
因此,您将看到,
不可变。Seq
是协变的,并使用第一个签名,而不可变。Set
是不变的,并使用第二个签名。注意:包含是使用包含[A1>:a](elem:A1)
中的来实现的(至少在Scala 2.11.8中). 我认为这与使用Any
不同-它对B
类型设置了一些限制-您可以传递Any
,但不能传递已知不相关的类型。@Suma当然可以。去试试吧。如果传递不相关的类型,A1
将被推断为公共超类型。因为所有东西都是从Any
派生的,所以所有类型都有一个共同的超类型。你说得对。那么,有什么原因可以解释为什么签名在库中保持原样,而不是像您写的那样使用any
?