2015-04-08 27 views
5

Khi tôi tìm hiểu nguồn thu thập gs cho ImmutableList, nó không mở rộng java.util.List. Tuy nhiên lớp javadoc đã đề cập rằng tất cả các triển khai ImmutableList phải thực hiện java.util.List.ImmutableList không mở rộng Danh sách?

Tại sao phải yêu cầu triển khai thực hiện java.util.List và không tự mở rộngđể mở rộng java.util.List?

+2

Điều gì * * mở rộng? –

+1

Tại gốc của nó, nó mở rộng 'java.lang.Iterable' – Wins

+0

Thiết kế lạ. Thay vì đặt một yêu cầu không thể thi hành vào Javadoc, họ chỉ có thể viết 'mở rộng java.util.Danh sách' và có nó được thực thi tự động. – EJP

Trả lời

11

Tại sao không ImmutableList mở rộng List?

ImmutableCollection không mở rộng java.util.Collection (và ImmutableList không mở rộng java.util.List) vì Collection đã biến đổi các phương pháp như add()remove(). Nếu các bộ sưu tập bất biến có các phương pháp này, chúng sẽ luôn phải ném UnsupportedOperationException. Đối với người dùng các bộ sưu tập không thay đổi, sẽ là lạ khi thấy add()remove() trong các lựa chọn tự động hoàn thành làm phương pháp có thể gọi.

Tại sao Javadoc áp đặt hợp đồng mà tất cả triển khai ImmutableList cũng thực hiện List?

Nó đi xuống bình đẳng. An ImmutableList phải bằng List, giả sử cả hai danh sách đều có cùng nội dung theo cùng thứ tự. List.equals() imposes a Javadoc contract trong đó nêu:

trả về true khi và chỉ khi các đối tượng quy định cũng là một danh sách, cả hai danh sách có cùng kích thước, và tất cả các cặp tương ứng của các nguyên tố trong hai danh sách đều bình đẳng.

Điều gì có nghĩa là "đối tượng được chỉ định cũng là danh sách?" Chúng ta có thể thấy trong AbstractList.equals() rằng nó có nghĩa là instanceof List.

public boolean equals(Object o) { 
    if (o == this) 
     return true; 
    if (!(o instanceof List)) 
     return false; 
    ... 
} 

Vì vậy, tất cả ImmutableList triển khai cũng phải thực hiện List cho equals() để làm việc một cách đối xứng. Các nhà máy thu gom không thay đổi đã ẩn chi tiết triển khai thực tế là danh sách bất biến với một phần tử đơn lẻ được thực hiện bởi ImmutableSingletonList. Nó cũng gió lên che giấu giao diện List.

ImmutableList class diagram

Interop

Một lợi ích của thiết kế này là ImmutableList có thể được đúc để List đó là quan trọng đối với interop với các API có sẵn.

// Library method - cannot refactor the parameter type 
public void printAll(List<?> list) 
{ 
    for (Object each : list) 
    { 
     System.out.println(each); 
    } 
} 

ImmutableList<Integer> immutableList = Lists.immutable.with(1, 2, 3); 
List<Integer> castList = immutableList.castToList(); 
printAll(castList); 
// also works 
printAll((List<?>) immutableList); 

// throws UnsupportedOperationException 
castList.add(4); 

Lưu ý: Tôi là một nhà phát triển trên GS Collections.

+2

Cảm ơn câu trả lời dài, có ý nghĩa, nhưng tôi đoán đó là một hương vị của thiết kế . Cá nhân tôi muốn có thêm() và remove() để ném UnsupportedOperationException thay vì gọi hàm castToList(). Nhà phát triển nên biết rằng nếu mã đang sử dụng ImmutableList, việc thêm và xóa sẽ không hoạt động và đó là vấn đề của nhà phát triển chứ không phải vấn đề thiết kế. Nhưng tôi đoán đó chỉ là ý kiến ​​cá nhân. Cảm ơn một lần nữa cho câu trả lời – Wins

+2

Tôi nghĩ rằng bạn có thể quan tâm đến UnmodifiableMutableList, và phương thức nhà máy MutableList.asUnmodifiable(). Tôi giữ câu trả lời này giới hạn trong ImmutableList nhưng cảm thấy tự do để đặt một câu hỏi mới về sự khác biệt và tôi sẽ quay lại và viết nhiều hơn. –

+2

Tôi hiểu UnmodifiableMutableList (tên rất rõ ràng), nhưng những gì tôi hỏi là tại sao không làm cho ImmutableList mở rộng List, ném UnsupportedOperationException vào add và remove, nhưng giữ lại tính bất biến của danh sách và các đối tượng chứa nó. – Wins

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