2010-05-27 28 views

Trả lời

23

lý do Iterable không có một phương pháp contains là bởi vì cách thức mà nó được định nghĩa có thể có những hậu quả trực tiếp trên vari ance. Về cơ bản, có hai chữ ký loại có ý nghĩa với nó:

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

Định nghĩa thứ hai đã tăng độ an toàn kiểu. Tuy nhiên, A, là tham số kiểu của bộ sưu tập, xuất hiện ở vị trí biến thể ngược, buộc tập hợp là bất biến. Nó thể được định nghĩa như thế này:

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

nhưng điều đó sẽ không cung cấp bất kỳ sự cải thiện so với chữ ký đầu tiên, sử dụng Any.

Kết quả là, bạn sẽ thấy rằng immutable.Seq là cùng biến thể và sử dụng chữ ký đầu tiên, trong khi immutable.Set là bất biến và sử dụng chữ ký thứ hai.

+0

Lưu ý: 'contains' ** được thực hiện bằng chữ ký' chứa [A1>: A] (elem: A1) 'trong' SeqLike' (ít nhất là trong Scala 2.11.8). Tôi không nghĩ rằng điều này cũng giống như sử dụng 'Bất kỳ' - nó đặt một số ràng buộc vào kiểu' B' - bạn có thể chuyển 'Bất kỳ', nhưng bạn không thể chuyển một kiểu được biết là không liên quan. – Suma

+0

@Suma Chắc chắn bạn có thể. Hãy tiếp tục và thử. Nếu bạn vượt qua một loại không liên quan, 'A1' sẽ được suy ra để trở thành siêu kiểu chung. Và bởi vì mọi thứ đều là hậu duệ của "Bất kỳ", sau đó tất cả các loại đều có một siêu kiểu chung với nhau. –

+0

Bạn nói đúng. Có bất kỳ lý do nào tại sao chữ ký trong thư viện như vậy không, và không phải với chữ "Bất kỳ", khi bạn viết, vậy thì sao? – Suma

5

Tôi không biết tại sao contains không được định nghĩa trên Iterable hoặc TraversableOnce, nhưng bạn có thể dễ dàng xác định nó cho mình:

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

và sử dụng nó như thể nó đã được xác định trên Iterable:

val iterable: Iterable[Int] = 1 to 4 
assert(iterable.contains(3)) 
assert(!iterable.contains(5)) 
Các vấn đề liên quan