Interfejsy wewnętrzne (inner interfaces) to interfejsy zdefiniowane wewnątrz innych klas lub interfejsów. Pojawiły się po raz pierwszy w języku w celu strukturyzacji dużych klas i ukrywania szczegółów implementacji. Taka enkapsulacja pozwala na logiczne grupowanie kontraktów, co znacząco poprawia czytelność i wsparcie kodu.
Od pierwszych wersji Javy pojawiła się możliwość definiowania statycznych i niestatycznych interfejsów wewnętrznych w klasach i innych interfejsach. Praktyka ta rozpowszechniła się w dużych bibliotekach (np. w kolekcjach Javy).
Nieprawidłowe rozumienie widoczności i zakresu użycia interfejsów wewnętrznych często prowadzi do błędów w projektowaniu API oraz do skomplikowania architektury aplikacji. Nie można ich używać jako członków instancji, zawsze są statyczne z natury.
Interfejsy wewnętrzne są stosowane do nadania bardziej modułowej struktury i wyróżnienia specyficznych kontraktów odnoszących się tylko do klasy otaczającej. Na przykład, interfejs Entry wewnątrz Map:
public interface Map<K, V> { interface Entry<K, V> { K getKey(); V getValue(); } Set<Entry<K, V>> entrySet(); }
Kluczowe cechy:
Pytanie 1: Czy można utworzyć instancję interfejsu wewnętrznego nie mając instancji klasy zewnętrznej?
Tak, instancję interfejsu wewnętrznego można zaimplementować oddzielnie, bez tworzenia obiektu zewnętrznego, ponieważ interfejs jest zagnieżdżony statycznie.
Pytanie 2: Jaki jest zakres widoczności interfejsu wewnętrznego w obrębie klasy?
Zakres widoczności regulują modyfikatory (public, protected, private, package-private). Jednak częściej są one definiowane jako publiczne, jeśli potrzebny jest dostęp z zewnątrz.
Pytanie 3: Czy interfejs wewnętrzny może zawierać interfejsy wewnętrzne?
Tak, dozwolona jest dowolna stopień zagnieżdżenia interfejsów, choć w praktyce zdarza się to rzadko z powodu obniżenia czytelności.
W jednym dużym projekcie zdefiniowano 10+ interfejsów wewnętrznych w klasie Service. Liczba powiązań rosła, nawigacja i zrozumienie kodu pogorszyły się.
Zalety:
Wady:
W klasie DataProcessor zdefiniowano interfejs wewnętrzny Validator, który został zaimplementowany tylko wewnątrz DataProcessor i nigdzie indziej.
Zalety:
Wady: