2013-05-07 25 views
6

Trong lớp java.util.Collections, chúng ta có hai biến thể của phương pháp sort, một trong đó có một danh sách các đối tượng tùy ý với một tương ứng Comparator:dịch các kí hiệu chung từ Java để Scala

public static <T> void sort(List<T> list, Comparator<? super T> comparator) 

Và một trong đó có một danh sách của Comparable đối tượng:

public static <T extends Comparable<? super T>> void sort(List<T> list) 

tôi đã suy nghĩ làm thế nào một woulds dịch chữ ký phương pháp như vậy với bo ký tự đại diện chưa hoàn thành vào Scala. Đối với phiên bản đầu tiên, tôi đã dịch chữ ký theo nghĩa đen và ngay từ cái nhìn đầu tiên không có vấn đề biên soạn:

def sort[T](list: List[T], comparator: Comparator[_ >: T]) { ??? } 

Nhưng sau đó tôi thấy rằng tôi không thể gọi phương pháp này với các đối số sau đây:

val comparator = new Comparator[Object] { 
    def compare(o1: Object, o2: Object) = ??? 
} 
val list = new ArrayList[Number] 
sort[Object](list, comparator) 

cuối cùng dòng cung cấp lỗi biên dịch này, mặc dù tôi chỉ định rõ ràng loại TObject.

loại không khớp; tìm thấy: java.util.ArrayList [Số] cần thiết: java.util.List [Object] Ghi chú: Số <: Đối tượng, nhưng Danh sách đặc điểm Java được định nghĩa là bất biến trong loại E. Bạn có thể muốn điều tra một loại ký tự đại diện như _ <: Object . (SLS 3.2.10)

Thực ra, tôi phát hiện ra rằng thậm chí không thể gọi phương thức Java duy nhất trực tiếp vì nó không thành công với cùng một loại lỗi.

Collections.sort[Object](list, comparator) 

Đối với các phiên bản với danh sách so sánh, tôi đã đưa ra tuyên bố này:

def sort[T <: Comparable[_ >: T]](list: List[T]) { ??? } 

Nhưng điều này không làm việc ở tất cả:

bất hợp pháp tài liệu tham khảo cyclic liên quan đến loại T


Tôi đang làm gì sai? Là biến thể Scala generics theo các quy tắc khác nhau của Java? Làm thế nào gọi một cuộc gọi phương pháp Collections.sort mà không thực sự nhận được một lỗi biên dịch?

Side lưu ý:

Không, tôi không thực sự hỏi làm thế nào tôi có thể sắp xếp một danh sách trong Scala. Tôi biết rằng Scala có bộ sưu tập riêng của mình, các chức năng sắp xếp và một cách tiếp cận khác để so sánh các đối tượng (chẳng hạn như OrderedOrdering đặc điểm). Câu hỏi của tôi liên quan đến vấn đề chung của các phương pháp chung và dịch các generics từ Java sang Scala.

Trả lời

4

Bạn đang đưa ra các tham số kiểu sai cho T: Bạn sắp xếp một List[Number], không phải là một List[Object]:

sort[Number](list, comparator) 

sẽ làm việc.

Nếu bạn muốn gọi loại mà không có một đối số kiểu, bạn cần xác định hai danh sách đối số (vì cách kiểu suy luận làm việc tại Scala):

def sort[T](list: List[T])(comparator: Comparator[_ >: T]) { ??? } 

// Then 
sort(list)(comparator) 

Bạn có thể muốn xem xét việc sử dụng các loại Scala, có sự hỗ trợ thích hợp cho hiệp phương sai (ví dụ: trong Scala a List[Number]List[Object]).

Liên quan đến phiên bản với so sánh, bạn sẽ phải viết một cách rõ ràng wildcard:

def sort[T <: Comparable[T], U <: T](list: List[U]) { ??? } 
+0

Được rồi, tôi thấy lỗi này ngay bây giờ! Ngay cả trong Java, mã máy khách sẽ cần phải là 'Bộ sưu tập. sắp xếp (danh sách, so sánh) ', không phải' Bộ sưu tập. sắp xếp (danh sách, so sánh) '. – Natix

+0

Ngoài ra, một lưu ý tuyệt vời về việc tách danh sách đối số, tôi đã không nhận thức được điều đó! Bạn cũng có thể xây dựng trên phiên bản với danh sách 'Comparable'? – Natix

+0

@Natix Xem câu trả lời cập nhật. – gzm0

3

Bạn có thể gọi các biến thể Java (hoặc của bạn) với:

Collections.sort[Number](list, comparator) 

Vấn đề ở đây là vì các kiểu Java chung là bất biến. Nói cách khác, điều này không thành công trong Java:

List<Number> l1; 
List<Integer> l2 = l1; //contravariance fails 
List<Object> l3 = l1; //covariance fails 

Trong Scala, các tham số kiểu chung có thể được khai báo là biến thể hoặc contravariant trong khai báo của chúng. Tham số kiểu List của Scala được khai báo là covariant (hoạt động vì nó không thay đổi). Nói cách khác, đây là hợp lệ:

val l1: List[Number] = ??? 
val l2: List[Object] = l1 //valid 

Nhưng kể từ khi bạn đang sử dụng Java java.util.List đó không phải là một lựa chọn.

+0

À đúng rồi, giờ tôi thấy sai rồi! Ngay cả trong Java, mã máy khách sẽ cần phải là 'Bộ sưu tập. sắp xếp (danh sách, so sánh) ', không phải' Bộ sưu tập. sắp xếp (danh sách, so sánh) '. – Natix

+0

Bạn cũng có thể xây dựng trên phiên bản với danh sách 'So sánh 'được không? Nhân tiện, tôi nghĩ rằng tham số kiểu danh sách của Scala thực sự là _covariant_ ('List [+ A]'). – Natix

+0

@Natix: Tôi ước tôi có thể trả lời câu hỏi của bạn về trường hợp có thể so sánh. Tôi vừa mới được giới thiệu với Scala từ Java, và những gì bạn có là tương đương trực tiếp về những gì tôi sẽ làm trong Java (và thực sự đây là những gì thực hiện thực hiện). Có vẻ như quá mức cần thiết để yêu cầu tham số loại thứ hai. –

Các vấn đề liên quan