2010-05-27 20 views

Respuesta

23

la razón Iterable no tiene un método contains se debe a la forma en que se define puede tener consecuencias directas sobre vari ance. Básicamente, hay dos tipos de firmas que tienen sentido para él:

def contains(v: Any): Boolean 
def contains(v: A): Boolean 

La segunda definición ha aumentado la seguridad del tipo. Sin embargo, A, que es el parámetro de tipo de colección, aparece en una posición contravariante, lo que obliga a la colección a ser invariante. Se podría definirse así:

def contains[B >: A](v: B): Boolean 

pero que no ofrecería ninguna mejora con respecto a la primera firma, utilizando Any.

Como consecuencia de esto, verá que immutable.Seq es covariante y utiliza la primera firma, mientras que immutable.Set es invariable y utiliza la segunda firma.

+0

Nota: 'contains' ** está ** implementado usando la firma' contiene [A1>: A] (elem: A1) 'en' SeqLike' (al menos en Scala 2.11.8). No creo que esto sea lo mismo que usar 'Any' - pone algunas restricciones en el tipo' B' - puedes pasar 'Any', pero no puedes pasar un tipo que se sabe que no está relacionado. – Suma

+0

@Suma Seguro que puedes. Adelante, inténtalo. Si pasa un tipo no relacionado, se deducirá que 'A1' es el supertipo común. Y como todo es descendiente de 'Any', todos los tipos tienen un supertipo común entre ellos. –

+0

Tienes razón. ¿Hay alguna razón por la cual la firma está en la biblioteca tal como está, y no con 'Any', mientras escribe, entonces? – Suma

5

No sé qué contains no está definido en Iterable o TraversableOnce, pero aquí se puede definir usted mismo:

class TraversableWithContains[A](underlying: TraversableOnce[A]) { 
    def contains(v: Any): Boolean = 
    underlying.exists(_ == v) 
} 
implicit def addContains[A](i: Iterable[A]) = new TraversableWithContains(i) 

y utilizarlo como si estuviera definido en Iterable:

val iterable: Iterable[Int] = 1 to 4 
assert(iterable.contains(3)) 
assert(!iterable.contains(5)) 
Cuestiones relacionadas