2010-05-27 10 views

risposta

23

la ragione Iterable non ha un metodo contains è perché il modo in cui viene definito può avere conseguenze dirette sui vari ANCE. Fondamentalmente, ci sono due firme tipo che hanno senso per esso:

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

La seconda definizione è aumentata sicurezza tipo. Tuttavia, A, che è il parametro type della raccolta, appare in una posizione contraria alla variante, che forza la collezione a essere invariata. Si potrebbe essere definito in questo modo:

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

ma che non offrirebbe alcun miglioramento rispetto al primo firma, utilizzando Any.

Come conseguenza di ciò, vedrete che immutable.Seq è in co-variante e utilizza la prima firma, mentre immutable.Set è invariante e utilizza la seconda firma.

+0

Nota: 'contains' ** è ** implementato utilizzando la firma' contiene [A1>: A] (elem: A1) 'in' SeqLike' (almeno in Scala 2.11.8). Non penso che questo sia lo stesso che usare 'Any' - pone alcuni vincoli sul tipo' B' - puoi passare 'Any', ma non puoi passare un tipo che è noto per non essere correlato. – Suma

+0

@Suma Certo che puoi. Vai avanti e prova. Se si passa un tipo non correlato, 'A1' sarà considerato il supertipo comune. E poiché tutto è discendente da "Qualsiasi", tutti i tipi hanno un supertipo comune tra loro. –

+0

Hai ragione. C'è qualche ragione per cui la firma nella libreria così com'è, e non con 'Any', come scrivi, allora? – Suma

5

Non so perché contains non è definito sulla Iterable o TraversableOnce, ma si potrebbe facilmente definire da soli:

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

e usarlo come se fosse definita Iterable:

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