Przechodziłem przez to pytanie Czy istnieje sposób na przesłonięcie zmiennych klas w Javie? Pierwszy komentarz z 36 głosami za:
Jeśli kiedykolwiek zobaczysz
protected static
, uciekaj.
Czy ktoś może wyjaśnić, dlaczego się nie protected static
zgadza?
final
. Zmienne pole statyczne współdzielone między klasami jest zdecydowanie powodem do zmartwień. Wiele klas aktualizujących pole statyczne prawdopodobnie nie będzie niezawodne lub łatwe do naśladowania, zwłaszcza że obecność jakiegokolwiek chronionego pola lub metody oznacza, że klasa ma zostać rozszerzona o klasy w innych pakietach, być może klasy nie będące pod kontrolą autor klasy zawierającej chronione pole.final
nie oznacza, że pole jest niezmienne. Zawsze możesz zmodyfikowaćobject
odwołanie za pomocąfinal
zmiennej odniesienia.Odpowiedzi:
To bardziej kwestia stylistyczna niż bezpośredni problem. Sugeruje, że nie przemyślałeś właściwie tego, co dzieje się na zajęciach.
Zastanów się, co to
static
znaczy:Zastanów się, co to
protected
znaczy:Te dwa znaczenia nie wykluczają się wzajemnie, ale są dość bliskie.
Jedynym przypadkiem, w którym mogę zobaczyć, gdzie możesz użyć tych dwóch razem, jest to, że masz klasę abstrakcyjną, która została zaprojektowana do rozszerzania, a klasa rozszerzająca mogłaby następnie zmodyfikować zachowanie za pomocą stałych zdefiniowanych w oryginale. Taki układ najprawdopodobniej skończyłby się jednak bardzo niechlujnie i wskazuje na słabość w projekcie zajęć.
W większości przypadków lepiej byłoby mieć stałe jako publiczne, ponieważ to po prostu czyni wszystko czystszym i pozwala ludziom na tworzenie podklas na większą elastyczność. Zupełnie niezależnie od wszystkiego innego, w wielu przypadkach kompozycja jest lepsza niż dziedziczenie, podczas gdy klasy abstrakcyjne wymuszają dziedziczenie.
Aby zobaczyć jeden przykład, jak to może zepsuć rzeczy i zilustrować, co mam na myśli mówiąc, że zmienna nie ma niezależnego istnienia, spróbuj tego przykładowego kodu:
Zobaczysz wyniki:
Wypróbuj sam na: https://ideone.com/KM8u8O
Klasa
Test2
jest w stanie uzyskać dostęp do elementu statycznegotest
odTest
bez konieczności zakwalifikowania nazwy - ale nie dziedziczy albo dostać własną kopię. Patrzy dokładnie na ten sam obiekt w pamięci.źródło
Rectangle
) w celu dostosowania szerokości / wysokości w celu zapewnienia równości (forSquare
) przyniesie niepożądane rezultaty, jeśli każdy nadtyp zostanie zastąpiony instancją jego podtypu.Jest źle widziany, ponieważ jest sprzeczny.
Utworzenie zmiennej
protected
oznacza, że będzie ona używana w pakiecie lub dziedziczona w ramach podklasy .Uczynienie zmiennej
static
czyni ją członkiem klasy, eliminując zamiary jej dziedziczenia . Pozostawia to tylko zamiar użycia w pakiecie i mamypackage-private
do tego (bez modyfikatora).Jedyna sytuacja może znajdę to przydatna jest, jeśli zostały deklarując klasę, która powinna być użyta do uruchomienia aplikacji (jak JavaFX użytkownika
Application#launch
, a jedynie chciał móc uruchomić z podklasy. Jeśli ten sposób upewnić się, że metoda jest równieżfinal
do nie zezwalaj na ukrywanie . Ale to nie jest „norma” i prawdopodobnie zostało zaimplementowane, aby zapobiec zwiększaniu złożoności poprzez dodanie nowego sposobu uruchamiania aplikacji.Aby zobaczyć poziomy dostępu każdego modyfikatora, zobacz: Samouczki języka Java - kontrolowanie dostępu do elementów członkowskich klasy
źródło
static
wyeliminowałoby to zamiary dziedziczenia. Ponieważ moja podklasa w innym pakiecie nadal wymaga pola super, aby uzyskaćprotected
dostęp, mimo że jeststatic
.package-private
nie mogę pomócprotected static
. Ale to zapach kodu, stąd część „ uruchom ”. Modyfikatory dostępu i dziedziczenie to dwa różne tematy. Tak, nie będziesz mógł uzyskać dostępu do statycznego elementu członkowskiego z superklasy, jeśli byłpackage-private
. Alestatic
przede wszystkim nie powinieneś polegać na dziedziczeniu w odniesieniu do pól referencyjnych ; to oznaka złego projektu. Zauważysz, że próby zastąpieniastatic
metod nie dają żadnych wyników, co jest wyraźnym znakiem, że dziedziczenie nie jest oparte na klasach. Jeśli potrzebujesz dostępu poza zajęciami lub pakietem, powinno to byćpublic
private static
funkcjami użytkowymi, ale myślę, że ktoś może chcieć ulepszyć lub dostosować z mojej klasy, a te funkcje użytkowe mogą im również zapewnić wygodę.public
może nie być odpowiednie, ponieważ metody util nie są przeznaczone dla użytkownika instancji mojej klasy. Czy możesz mi pomóc zamiast tego wymyślić dobry projektprotected
? DziękiNie widzę konkretnego powodu, dla którego należałoby się na to źle patrzeć. Zawsze mogą istnieć alternatywy umożliwiające osiągnięcie tego samego zachowania i od aktualnej architektury będzie zależeć, czy te alternatywy są „lepsze” niż chroniona metoda statyczna, czy nie. Ale jeden przykład, w którym chroniona metoda statyczna byłaby rozsądna, może być przynajmniej następujący:
(Zredagowane w celu podzielenia na oddzielne pakiety, aby użyć
protected
jaśniejszego)Wywodzi się z tego:
Inna klasa pochodna:
protected static
Modyfikator może być z pewnością uzasadnione tutaj:static
, ponieważ nie zależą od zmiennych instancji. Nie są przeznaczone do bezpośredniego stosowania jako metoda polimorficzna, ale są raczej metodami „użytkowymi” oferującymi domyślne implementacje które są częścią bardziej złożonych obliczeń i służą jako „bloki konstrukcyjne” rzeczywistej implementacji.public
, ponieważ są szczegółem implementacji. I nie mogą być,private
ponieważ powinny być wywoływane przez klasy rozszerzające. Nie mogą też mieć widoczności „domyślnej”, ponieważ wtedy nie będą dostępne dla klas rozszerzających w innych pakietach.(EDYCJA: można by przypuszczać, że pierwotny komentarz dotyczył tylko pól , a nie metod - wtedy był jednak zbyt ogólny)
źródło
protected final
(ponieważ nie chcesz, aby były zastępowane), a niestatic
. Fakt, że metoda nie używa zmiennych instancji, nie oznacza, że tak powinno byćstatic
(chociaż może ).final
, nie tylko wyjaśnia, że metoda nie ma być nadpisywana, ale dodatkowo wyjaśnia czytelnikowi, że metoda nie używa zmiennych instancji. Tak zwięźle: po prostu nie ma powodu, aby nie robić tego statycznie.protected
, nie po to, by pokazać dziedziczenie, ale by zachować to w jednym pakiecie - nie ujawnianym. Myślę, że zapieczętowane interfejsy staną się pomocne w ten sposób, gdy będą w Javieprotected
oznacza „Dziedziczenie klas (nawet w różnych pakietach)” ...Statyczne elementy członkowskie nie są dziedziczone, a chronione elementy są widoczne tylko dla podklas (i oczywiście dla klasy zawierającej), więc
protected static
ma taką samą widoczność jakstatic
, co sugeruje nieporozumienie ze strony kodera.źródło
protected
nie są takie same. Jeśli powieszstatic
, pole jest widoczne tylko dla podklas w tym samym pakiecie.protected static
umożliwia dostęp w ramach pakietu lub z podklasy . Utworzenie zmiennej statycznej usuwa zamiar tworzenia podklas, pozostawiając jedynym celem jest dostęp z poziomu pakietu.Właściwie nie ma w tym zasadniczo nic złego
protected static
. Jeśli naprawdę potrzebujesz statycznej zmiennej lub metody, która jest widoczna dla pakietu i wszystkich podklas deklarującej klasy, to zrób toprotected static
.Niektórzy ludzie na ogół unikają używania
protected
z różnych powodów, a niektórzy uważają, żestatic
za wszelką cenę należy unikać zmiennych nieokreślonych (osobiście do pewnego stopnia sympatyzuję z tymi ostatnimi), więc myślę, że połączenieprotected
istatic
musi wyglądać źle ^ 2 dla tych, które należą do obu grup.źródło
Chroniony jest używany, więc może być używany w podklasach. Nie ma żadnej logiki w definiowaniu chronionej statycznej wartości statycznej, gdy jest ona używana w kontekście konkretnych klas, ponieważ dostęp do tej samej zmiennej jest statyczny, jednak mechanizm zgodności wyświetli ostrzeżenie, aby uzyskać dostęp do statycznej zmiennej superklasy w sposób statyczny.
źródło
Cóż, jak odpowiedziała większość ludzi:
protected
znaczy - ' pakiet-prywatny + widoczność do podklas - właściwość / zachowanie jest dziedziczone 'static
znaczy - ' przeciwieństwo instancji - jest to właściwość / zachowanie KLASY, tj. NIE JEST DZIEDZICZONY ”Dlatego są nieco sprzeczne i niekompatybilne.
Jednak ostatnio doszedłem do przypadku użycia, w którym sensowne może być użycie tych dwóch razem. Wyobraź sobie, że chcesz utworzyć
abstract
klasę, która jest rodzicem dla typów niezmiennych i ma kilka właściwości wspólnych dla podtypów. Aby poprawnie zaimplementować niezmienność i zachować czytelność, można zdecydować się na użycie wzorca Builder .A dlaczego
protected static
? Ponieważ chcę nieabstrakcyjnego podtypu,AbstactType
który implementuje własny nieabstrakcyjny Konstruktor i znajduje się na zewnątrz,package X
aby móc uzyskać dostęp do plikuBaseBuilder
.Oczywiście możemy podać do
BaseBuilder
wiadomości publicznej, ale potem dochodzimy do kolejnych sprzecznych stwierdzeń:Tak więc w obu przypadkach
protected static
ipublic
budowniczymabstract class
łączymy sprzeczne oświadczenia. To kwestia osobistych preferencji.Jednak nadal wolę
public
konstruktora,abstract class
ponieważprotected static
wydaje mi się bardziej nienaturalny w świecie OOD i OOP!źródło
Nie ma nic złego w posiadaniu
protected static
. Wiele osób przeoczyło jedną rzecz, ponieważ możesz chcieć napisać przypadki testowe dla metod statycznych, których nie chcesz ujawniać w normalnych okolicznościach. Zauważyłem, że jest to szczególnie przydatne do pisania testów dla metody statycznej w klasach narzędziowych.źródło