2015-03-04 13 views
5

Tôi có dòng mã sau đây:Scala Set [_] vs Set [Bất kỳ]

case set: Set[Any] => setFormat[Any].write(set) 

Tuy nhiên, trình biên dịch đưa ra một cảnh báo:

non-variable type argument Any in type pattern scala.collection.Set[Any] is unchecked since it is eliminated by erasure [warn]

đủ Fair.

Vì vậy, tôi thay đổi dòng của tôi như thế này:

case set: Set[_] => setFormat[Any].write(set) 

Bây giờ tôi nhận được một lỗi:

[error] found : scala.collection.Set[_]

[error] required: scala.collection.Set[Any]

Q1. sự khác biệt giữa hai cái đó là gì?

Sau đó, tôi thay đổi mã của tôi như sau:

case set: Set[_] => setFormat[Any].write(set.map(s => s)) 

Bây giờ nó là hạnh phúc không có lỗi hoặc cảnh báo.

Q2. Tại sao điều này làm việc ??

+0

bạn có thể cung cấp các loại/chữ ký của setFormat và viết không? –

+0

chỉ tò mò, không loại bỏ rõ ràng '[Bất kỳ]' và bản đồ, như được đề xuất trong câu trả lời của tôi dưới "Ghi chú", hoạt động trong trường hợp của bạn? –

Trả lời

12

Q1: A Set[Any] là Tập hợp có loại phần tử là Bất kỳ. A Set[_] là Tập hợp có loại phần tử không xác định. Có thể là Set[Int], có thể là Set[String], có thể là Set[Any]. Trái với hầu hết các bộ sưu tập (không thay đổi), Set không phải là biến thể (khai báo là trait Set[A], không phải trait Set[+A]). Vì vậy, Set[String] không phải là Set[Any] và thông thường hơn, bạn không thể đảm bảo rằng nhóm có loại yếu tố bạn không biết (ví dụ: Set[_]) là Set[Any].

Q2: Nó hoạt động vì bất kỳ loại (không rõ) A nào của các thành phần của tập hợp, chức năng nhận dạng s => s có thể được xem là một hàm A => Bất kỳ. (Đúng là Function1[-T1, +R] Sau đó, kết quả set.map(s => s) có thể được gõ như Set[Any], theo yêu cầu

Ghi chú:.. Khó để chắc chắn không có định nghĩa về setFormat và viết, nhưng bạn có thực sự cần phải được rõ ràng với [Any] kiểu lập luận trong setFormat[Any]? người ta có thể vượt qua một hiện sinh đến một hàm tổng quát, tức là

val x: X[_] = .... 
def f[A](xa: X[A]) = ... 
f(x) // allowed 

nhưng là rõ ràng tại địa điểm cuộc gọi (ví dụ f[Any](x)) sẽ không được phép, như chúng ta không biết liệu X là một X[Any].

Lưu ý: về Đặt không phải là biến thể: Điều này là không may, vì người ta cảm thấy rất nhiều rằng một bộ mèo là một tập hợp các loài động vật quá. Đây là một lý do cho điều đó (có thể có những người khác).

Đặt có phương thức def contains(a: A): Boolean và chữ ký này ngăn ngừa hiệp phương sai. Các bộ sưu tập khác có def contains[A1 >: A](a: A): Boolean, cho phép hiệp phương sai, nhưng có hiệu quả tương đương với def contains(a: Any): Boolean.

Nó hoạt động, bởi vì việc triển khai dựa trên phương pháp equals, có sẵn ở khắp mọi nơi (đi kèm với JVM) và có đối số kiểu Any. Rất có khả năng việc gọi với giá trị của một loại không liên quan đến nội dung danh sách là một sai lầm, và một chữ ký hạn chế hơn sẽ tốt hơn, nhưng đó là một mức giá nhỏ để trả cho hiệp phương sai.

Nhưng chữ ký thoải mái này dành cho contains ràng buộc việc triển khai dựa trên equals (và có thể cả hashCode cũng vậy). Nó sẽ không làm việc cho một thực hiện dựa trên Ordering, mà sẽ không chấp nhận một đối số untyped. Việc cấm việc triển khai tập hợp (rất phổ biến) như vậy có thể được xem là giá quá cao cho hiệp phương sai.

+1

xem thêm http://stackoverflow.com/q/676615/86485 ("Tại sao Bộ bất biến của Scala không phải là biến thể trong loại của nó?") –