Dlaczego nie można zdefiniować klasy jako chronionej?


89

Dlaczego nie możemy zdefiniować klasy jako protected?

Wiem, że nie możemy, ale dlaczego? Powinien być jakiś konkretny powód.


3
Co by się stało , gdybyś zadeklarował klasę jako chronioną?

1
Myślę, że właśnie tego szukasz: stackoverflow.com/questions/2534733/java-protected-classes : D
dewijones92

2
Powiedzmy tylko, dlaczego nie można chronić klasy zewnętrznej? Klasy wewnętrzne mogą być chronione.
Number945

Odpowiedzi:


101

Bo to nie ma sensu.

Chroniony element członkowski klasy (metoda lub zmienna) jest podobny do prywatnego pakietu (domyślna widoczność), z tym wyjątkiem, że można uzyskać do niego dostęp również z podklas.
Ponieważ w Javie nie ma pojęcia „podpakiet” lub „dziedziczenie pakietu”, zadeklarowanie klasy chronionej lub pakietu prywatnego byłoby tym samym.

Możesz jednak zadeklarować klasy zagnieżdżone i wewnętrzne jako chronione lub prywatne.


> Ponieważ w Javie nie ma pojęcia „podpakiet” lub „dziedziczenie pakietu”, zadeklarowanie klasy chronionej lub pakietu prywatnego byłoby tym samym. Dlaczego klasa chroniona miałaby taką samą widoczność jak pakiet prywatny? Czy to nie to samo, co publiczne? Dzięki.
yaromir

@Nikita Ryback Czy możesz wyjaśnić, czym jest subPakiet lub dziedziczenie pakietu? Nie wiem, dlaczego chroniony jest używany w klasie najwyższego poziomu. Jeśli wyjaśnisz na przykładzie, będzie świetnie.
App Kart

Kiedy deklarujesz element członkowski klasy jako chroniony, jego widoczność to klasy z tego samego pakietu (nazywanego dostępem do pakietu) i podklasy . Jeśli spróbujesz uzyskać dostęp z klasy zewnętrznej w innym pakiecie, ten element członkowski metody chronionej nie jest widoczny.
kelgwiin

@kelgwiin Uważam, że nie należy mieszać modyfikatorów dostępu klas i członków. Ponieważ te dwa są różne. Podczas gdy klasy mogą być modyfikowane jako publiczne lub domyślne, członkowie mogą być modyfikowani jako publiczne, prywatne, chronione i domyślne.
sharhp

2
„Bo to nie ma sensu” - to dość odważne stwierdzenie. To nie jest zdefiniowane w Javie, ale podobne rzeczy nie istnieją; np. openw Kotlinie, który pozwala na tworzenie podklas poza bieżącym pakietem (można sobie wyobrazić protectedw Javie, który temu zapobiega, z przeciwnym domyślnym).
Raphael,

41

Jak wiesz, domyślnym jest dostęp na poziomie pakietu, a chroniony jest dla poziomu pakietu plus klasy niebędące pakietami, ale rozszerza tę klasę (należy tu zauważyć, że możesz rozszerzyć klasę tylko wtedy, gdy jest widoczna!). Ujmijmy to w ten sposób:

  • chroniona klasa najwyższego poziomu byłaby widoczna dla klas w swoim pakiecie.
  • teraz uczynienie go widocznym poza pakietem (podklasami) jest nieco zagmatwane i trudne. Które klasy powinny mieć możliwość dziedziczenia naszej chronionej klasy?
  • Jeśli wszystkie klasy mogą tworzyć podklasy, będzie to podobne do specyfikatora dostępu publicznego.
  • Jeśli żaden, to jest podobny do default.

Ponieważ nie ma możliwości ograniczenia podklasy tej klasy tylko przez kilka klas (nie możemy ograniczyć dziedziczenia klasy przez tylko kilka klas ze wszystkich dostępnych klas w pakiecie / poza pakietem), nie ma zastosowania specyfikatorów dostępu chronionego dla klas na najwyższym poziomie. Dlatego nie jest to dozwolone.


3
„teraz uczynienie chronionej klasy widoczną poza pakietem (podklasami) jest nieco zagmatwane i skomplikowane. Które klasy powinny dziedziczyć naszą chronioną klasę? i Jeśli wszystkie klasy mogą tworzyć podklasy, będzie to podobne do specyfikatora dostępu publicznego”. naprawdę pomogło mi zrozumieć problem, dlaczego chronione klasy nie mają sensu :)
user1338998


3

@Nikita Rybak odpowiedź ma dobre strony, ale brak szczegółów, nie mogę po prostu zrozumieć pomysłu bez głębokiego przemyślenia, oto co myślałem, a teraz powinienem całkowicie zrozumieć powód.

Cztery modyfikatory dostępu, załóżmy, że pierwszy poziom jest publiczny, a czwarty poziom prywatny (na podstawie tej tabeli w kolejności). Pierwszą rzeczą, którą powinniśmy wiedzieć, jest to, dlaczego klasa nie może być zdefiniowana jako prywatna na najwyższym poziomie.

Więc jeśli "private class foo" (zdefiniowany prywatny element członkowski, tj. Sama klasa jest członkiem) zezwala, jaka jest zewnętrzna (zawierająca element)? Zakres pliku? Nie, zewnętrzny plik jest bezcelowy, ponieważ nawet wiele klas w jednym pliku zostanie skompilowanych w oddzielne pliki klas. Więc na zewnątrz jest pakiet . Ale domyślny modyfikator dostępu trzeciego poziomu już oznacza „prywatny pakiet ”. Zatem modyfikator dostępu prywatnego czwartego poziomu nie będzie używany / dozwolony.

Ale zagnieżdżona klasa prywatna jest dozwolona, ​​ponieważ bezpośrednia zewnętrzna jest klasą, a nie pakietem, np . :

class PrivateNestedMain {
    private static class Inner {
        public static void main(String[] args) {
            System.out.println("Hello from Inner!");
        }
    }
}

A co, jeśli zezwala na to „chroniona klasa foo”? chronioną cechą główną jest podklasa, więc zewnętrzna (pakiet) POWINNA (ze względu na up-to zakres, ale nadal jest opcjonalna) podać styl podklasy , tj. sub-pakietu, lub package A extends package B, ale nic takiego nie wiemy. Tak więc chroniony nie może wykorzystać pełnego potencjału (główny zakres obejmuje podklasę) na najwyższym poziomie, którym jest pakiet zewnętrzny (tj. Nie ma takiego pakietu podrzędnego), ale chroniony może wykorzystać pełny potencjał w zagnieżdżonej klasie, której zewnętrzna jest klasa ( czyli może być podklasą) :

class ProtectedNestedMain {
    protected static class Inner {
        public static void main(String[] args) {
            System.out.println("Hello from Inner!");
        }
    }
}

Zwróć uwagę, że powyższe „nie może wykorzystać pełnego potencjału”, ponieważ nie może dotrzeć do całej podklasy tylko dlatego, że nie ma zewnętrznej podklasy, co oznacza, że faktycznie można zezwolić na ochronę , jest to tylko kwestia wyboru, aby uniknąć powielania zadania pakietu -private, jeśli zewnętrzna nie może mieć podklasy , patrz poniżej.

Moje zagubienie jest spowodowane głównie przez słynną tabelę na https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html :

wprowadź opis obrazu tutaj

Jeśli dozwolony jest poziom 1 (publiczny) i 3 poziom (pakiet prywatny), to jak u licha poziom pośredni (chroniony) jest niedozwolony?

podklasa wsparcia publicznego, tak łatwa do wprowadzenia w błąd. Prawidłowy sposób odczytania tej tabeli to

publiczna podklasa wsparcia, jeśli zewnętrzna ma funkcję podklasy.

To samo mylące dotyczy pakiet-prywatny, pakiet-prywatny nie obsługuje podklasy ( N w komórce) nie oznacza, że ​​pojęcie podklasy ma zastosowanie w zewnętrznym.

Oznacza to, że powinniśmy zignorować kolumnę Subclass, jeśli funkcja podklasy nie jest dostępna w zewnętrznym:

wprowadź opis obrazu tutaj

Jak widzimy teraz, zarówno chroniony, jak i prywatny pakiet są teraz na tym samym poziomie ( YYN ), koniec z nieporozumieniami co do tego, dlaczego poziom pośredni jest niedozwolony. Ogólnie rzecz biorąc, Java wybiera tylko pakiet prywatny, a nie chroniony, aby uniknąć nieporozumień ( to tylko kwestia wyboru , ale główną cechą chronioną jest podklasa, więc pakiet prywatny jest lepszy), w wyniku czego dozwolone są tylko 2 modyfikatory dostępu na najwyższym poziomie:

Na najwyższym poziomie - publiczny lub prywatny pakiet (bez jawnego modyfikatora).


3

Zdefiniowanie chronionego pola sprawia, że ​​to pole jest dostępne zarówno wewnątrz pakietu, jak i poza pakietem tylko poprzez dziedziczenie (tylko w klasie potomnej).

Więc jeśli możemy uczynić klasę chronioną, możemy bardzo łatwo uzyskać do niej dostęp wewnątrz pakietu, ale aby uzyskać dostęp do tej klasy poza pakietem, najpierw musimy rozszerzyć tę jednostkę, w której ta klasa jest zdefiniowana, która jest jej pakietem.

A ponieważ pakietu nie można rozszerzyć (można go zaimportować), zdefiniowanie klasy chronionej ponownie sprawi, że pakiet będzie prywatny, co jest podobne do zdefiniowania go jako domyślnego, co już możemy zrobić. Dlatego nie ma żadnej korzyści z definiowania klasy prywatnej, a jedynie sprawi, że rzeczy będą niejasne.

Aby uzyskać więcej informacji, przeczytaj Dlaczego zewnętrzna klasa Java nie może być prywatna ani chroniona


3
Proszę ujawnić wszelkie powiązania i nie wykorzystywać tej witryny do promowania swojej witryny poprzez publikowanie. Zobacz: Jak napisać dobrą odpowiedź? .

1

Chroniony nie jest podobny do publicznego. Protected ma zarówno dostęp na poziomie pakietu, jak i można uzyskać do niego dostęp spoza pakietów tylko przez dziedziczenie. ma chronione metody, ale podklasy wywodzące się z tej klasy, tj. A nie może uzyskać dostępu do metod chronionych .. odwrotnie dzieje się z publicznymi ..

Przykład:

package 2;
class B
{
protected void method1()
{
}
}
package 1;
import 2.B;
class A extends B
{
//can access protected method
}
class C extends A
{
//can't access the protected method
}

0

zachowanie „protected” = zachowanie „default” + „użyj go w dowolnej podklasie w dowolnym pakiecie”.

W każdym razie mamy domyślny modyfikator dostępu dla klasy, jedyną zaletą, jaką możemy uzyskać z modyfikatora dostępu chronionego jest: - użycie go w dowolnym pakiecie poprzez podklasy. Ale w przypadku podklasy widoczność „chronionej” klasy nadrzędnej byłaby prywatna. Więc nie można uzyskać do niego dostępu. Zasadniczo, jeśli masz chronioną klasę najwyższego poziomu, żadna klasa zewnętrzna nie może uzyskać dostępu przez tworzenie podklas. Tak chroniony dla klasy na najwyższym poziomie jest bez znaczenia.


0

Chroniony : WIDOCZNY tylko na poziomie pakietu *.

klasa jest zdefiniowana jako chroniona ---> nie można jej rozszerzyć z zewnątrz pakietu (niewidoczne).

A jeśli nie można go rozszerzyć, nie ma sensu utrzymywać go jako chronionego , ponieważ wtedy stanie się domyślnym dostępem, który jest dozwolony.

To samo dotyczy prywatnych klas zdefiniowanych.

Uwaga: Klasy zagnieżdżone lub wewnętrzne można zdefiniować jako chronione lub prywatne .

* : Przeglądaj chronione słowo kluczowe, w tej odpowiedzi zawarłem.


0

Odpowiedź od @ Akash5288 nie miała dla mnie sensu:

Jeśli wszystkie klasy mogą tworzyć podklasy, będzie to podobne do specyfikatora dostępu publicznego.

Ponieważ nie ma możliwości ograniczenia podklasy tej klasy tylko przez kilka klas (nie możemy ograniczyć dziedziczenia klasy przez tylko kilka klas ze wszystkich dostępnych klas w pakiecie / poza pakietem), nie ma zastosowania specyfikatorów dostępu chronionego dla klas na najwyższym poziomie. Dlatego nie jest to dozwolone.

Możesz następnie zastosować tę samą logikę do chronionych metod i zmiennych, są one również „podobne do publicznych”. Wszystkie klasy poza pakietem mogą rozszerzać naszą klasę publiczną i używać jej chronionych metod. Dlaczego ograniczanie metod i zmiennych do klas rozszerzonych jest w porządku, ale ograniczanie całej klasy nie jest w porządku? „Podobny do publicznego” nie jest „taki sam jak publiczny”. Moja interpretacja jest taka, że ​​dopuszczenie klasy chronionej jest w porządku, podobnie jak dopuszczenie metod chronionych.

Odpowiedź „nie możesz rozszerzyć klasy, do której nie masz dostępu / nie widzisz” jest bardziej logiczna.


0

To, co ma sens w przypadku tego pytania, to fakt, że JVM jest napisane w C (Sun JVM) i C ++ (Oracle JVM), więc podczas kompilacji utworzymy pliki .class z naszego pliku java i jeśli zadeklarujemy klasę ze słowem kluczowym Protected wtedy JVM nie uzyska do niego dostępu.

Odpowiedź, dlaczego chroniona klasa nie będzie dostępna dla JVM, jest taka, że ​​ponieważ chronione pola są dostępne w ramach tego samego pakietu lub do innego pakietu tylko poprzez dziedziczenie, a JVM nie jest napisana w taki sposób, że będzie dziedziczyć klasę. Mam nadzieję, że to odpowiada na to pytanie :)

Podobnie zajęcia najwyższego poziomu nie mogą być prywatne. Wyjaśnienie jak poniżej:

A więc co się stanie, jeśli zdefiniujemy klasę private, która będzie dostępna tylko w ramach encji, w której jest zdefiniowana, która w naszym przypadku jest jej pakietem?

Tak więc zdefiniowanie prywatnego dostępu do klasy sprawi, że będzie ona dostępna w tym samym pakiecie, co domyślne słowo kluczowe już dla nas robi. Dlatego nie ma żadnej korzyści z definiowania klasy prywatnej, tylko sprawi, że rzeczy będą niejednoznaczne.


0

chroniony oznacza, że ​​do członka można uzyskać dostęp przez dowolną klasę w tym samym pakiecie i przez podklasy, nawet jeśli znajdują się one w innych pakietach.

Przykład:

package a;
class parent{
 protected void p();
}
package b;
import a.p;
class child extends parent{
  //you can access method which is protected in the parent in the child 
}
class another extends child {
 //here you can not access the protected method 
}

0

jeśli klasa zewnętrzna jest zadeklarowana przez protected, myślę, że chcesz, aby dostęp do tej klasy był możliwy tylko z tego samego pakietu i jego podklasy, ale z różnych pakietów. Jednak nie ma możliwości tworzenia podklas dla klasy chronionej, ponieważ kiedy piszesz „class Dog extends Animal”, z powodu chronionej „Animal” można uzyskać dostęp tylko przez jego podklasę, oczywiście „Dog” nie jest podklasą „Animal” .

Tak więc chroniona klasa zewnętrzna jest taka sama jak (domyślna) klasa zewnętrzna!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.