Wszystko jasne ale chciałbym w takim razie zapytać jaki jest cel tworzenia konstruktora protected?
Cel jest bardzo prosty - jak wszystko czemu służy dostęp protected
- do używania przez klasy pochodne. Na przykład ostatnio potrzebowałem mapy haszującej, która czasem miała się zachowywać zupełnie normalnie, a czasem miała używać czegoś innego do odczytu kodu hash obiektu i równości niż hashCode
i equals
elementów w mapie. Ponieważ rzeczy tych nie można zmieniać w czasie działania mapy (rozwaliłoby to dane), więc takie zmiany można przeprowadzić tylko w konstruktorze. Z drugiej strony klient nie miał mieć jakiegokolwiek dostępu do przeprowadzania takiej modyfikacji mapy. Jednym z rozwiązań było stworzenie konstruktora protected
mającego parametr ustalający typ mapy, tak aby móc stworzyć mapę "zwykłą", tożsamościową oraz specjalną, której equals
i hashCode
elementów pochodziły z zewnętrznego źródła. W ten sposób za pomocą tego samego kodu zawartego w klasie abstrakcyjnej i jej konstruktora chronionego mogłem sobie banalnie wyprowadzić ze zwykłej mapy haszującej dwie dodatkowe klasy konkretne, które dawały mi mapę tożsamościową i zrzucającą kody hash do cache (jako przykład). Mógłbym też zrobić jedną bazę abstrakcyjną i wyprowadzić z niej 3 klasy map. W każdym wypadku był mi potrzebny konstruktor protected
.
Inny przykład: Potrzebowałem kolekcji, której jedyną cechą było to, że jej elementy miały być iterowalne za pomocą listIteratora (czyli również indeksowane). Kolekcje takie mogły być zarówno tylko do odczytu z możliwością importu z innych danych (w tym z tej samej kolekcji), jak i z wersją w pełni modyfikowalną. Na dodatek zależnie od tego jak kolekcja została zainicjowana jej iterator miał obsługiwać metody remove
, add
i set
, albo rzucać wyjątkiem UnsupportedOperationException
. Zrobiłem więc sobie abstrakcyjną bazę AbstractIterable z konstruktorem protected
, który przyjmował boolean modifiable
i wrzucał to jako pole w bazie. Zależnie od tej informacji iterator w tej i każdej klasie pochodnej albo pozwalał użyć metod modyfikujące kolekcję, albo rzucał z nich wyjątkiem (metody iteratora odczytywały to pole).
Krótko mówiąc dopóki nie masz rozbudowanych gałęzi klas, to konstruktor chroniony nie będzie Ci do niczego potrzebny. Kiedy tych klas będzie dużo na tyle, że warto będzie powtarzające się elementy kodu pakować jako klasy bazowe wtedy będziesz potrzebować konstruktorów chronionych.