Dlaczego ImmutableList
przedłużyć List
?
ImmutableCollection
nie rozciąga java.util.Collection
(i ImmutableList
nie rozciąga java.util.List
), ponieważ Collection
ma mutację metod, takich jak add()
i remove()
. Gdyby niezmienne zbiory miały te metody, zawsze musiałyby rzucać UnsupportedOperationException
. Dla użytkowników niezmiennych kolekcji, byłoby dziwne, gdyby opcje autouzupełniania były dostępne jako metody wywoływalne.
Dlaczego Javadoc narzuca umowę, że wszystkie implementacje ImmutableList
implementują również List
?
Sprowadza się do równości. Numer ImmutableList
powinien być równy List
, zakładając, że obie listy mają tę samą zawartość w tej samej kolejności. List.equals()
imposes a Javadoc contract który stanowi:
Zwraca true wtedy i tylko wtedy, gdy określony obiekt jest także lista obie wykazy mają tę samą wielkość, a wszystkie odpowiadające im pary elementów dwie listy są równe.
Co to znaczy, że "określony obiekt to także lista?" Możemy zobaczyć w AbstractList.equals()
, że oznacza to instanceof List
.
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
...
}
Więc wszystkie ImmutableList
implementacje muszą też wdrożyć List
dla equals()
pracować w sposób symetryczny. Niezmienne fabryki kolekcji już ukrywają szczegóły implementacji, takie jak fakt, że niezmienna lista z pojedynczym elementem jest zaimplementowana przez ImmutableSingletonList
. Zapełnia się również ukrywanie interfejsu List
.
Interop
Zaletą tego rozwiązania jest to, że ImmutableList
można odlewać do List
co jest ważne dla współdziałanie z istniejącymi API.
// 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);
Uwaga: Jestem deweloperem na GS Collections.
Co * nie * rozszerza? –
W katalogu głównym rozszerza 'java.lang.Iterable' – Wins
Dziwny wzór. Zamiast umieszczać niewykonalne wymagania w Javadoc, mogli napisać: 'extends java.util.Lista' i wymuszenie go automatycznie. – EJP