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()
và 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()
và 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
.
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.
Nguồn
2015-04-08 14:34:51
Điều gì * * mở rộng? –
Tại gốc của nó, nó mở rộng 'java.lang.Iterable' – Wins
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