2013-08-28 6 views
22

Widziałem różne artykuły na temat różnic między chronionymi i pakietowymi modyfikatorami prywatnymi. Jedną rzeczą znalazłem sprzeczności między tymi dwoma stanowiskróżnice między modyfikatorami chronionymi i pakietowymi prywatnymi w Javie?

  1. Isn't "package private" member access synonymous with the default (no-modifier) access?

    W ten przyjętą odpowiedź mówi, że

    Zabezpieczony modyfikator określa, że ​​państwa mogą być dostępne tylko w ramach własnej opakowaniu (tak jak w przypadku pakietu-private), a dodatkowo przez podklasę swojej klasy w innym pakiecie.

  2. Why the protected modifier behave differently here in Java subclass?

    W tym zaakceptowanej odpowiedzi mówi, że

    Aby zaspokoić Protected Access poziomu muszą być spełnione dwa warunki:

    • Zajęcia muszą być w tym samym opakowaniu .
    • Musi istnieć relacja dziedziczenia.

nie są one sprzeczne? Z mojego zrozumienia innych artykułów, pierwszy post daje prawidłową odpowiedź, która chroniła == pakiet-prywatny + podklasa w innym pakiecie.

Jeśli to stwierdzenie jest prawdziwe, to dlaczego tego kodu nie powiedzie się z następującym komunikatem o błędzie na moim podklasy Kotka na linii 17

The method testInstanceMethod() from the type Animal is not visible 

mój kod Super i podklasy są poniżej.

package inheritance; 

public class Animal { 

    public static void testClassMethod() { 
     System.out.println("The class" + " method in Animal."); 
    } 
    protected void testInstanceMethod() { 
     System.out.println("The instance " + " method in Animal."); 
    } 
} 

package testpackage; 

import inheritance.Animal; 

public class Cat extends Animal{ 
     public static void testClassMethod() { 
      System.out.println("The class method" + " in Cat."); 
     } 
     public void testInstanceMethod() { 
      System.out.println("The instance method" + " in Cat."); 
     } 

     public static void main(String[] args) { 
      Cat myCat = new Cat(); 
      Animal myAnimal = myCat; 
      myAnimal.testClassMethod(); 
      myAnimal.testInstanceMethod(); 
     } 
    } 

Proszę wyjaśnić, dlaczego powyższy kod nie powiedzie się. To byłoby bardzo przydatne. Dzięki

+1

Musisz być kotem, aby użyć metody testInstanceMethod(). Casting to Animal ogranicza dostęp do tej metody do pakietu, a ponieważ twoja główna jest w innym pakiecie, kod zawodzi. (Myślę, że nie skompilowałoby się). Tak, istnieje ta metoda, ale nie masz uprawnień dostępu do niej, ponieważ jest ona zadeklarowana w Animal przez chronione. – PSIXO

+0

Drugie stwierdzenie powinno być sformułowane jako: * "Aby spełnić poziom chronionego dostępu, ** jeden z ** dwóch warunków musi być spełniony ..." * (Zobacz także komentarz, który napisałem poniżej tej odpowiedzi.) – aioobe

Odpowiedz

21

Pierwsza odpowiedź jest w zasadzie poprawna - protected członkowie mogą być dostępne przez

  • zajęć z tego samego pakietu
  • podklasy klasy uznającej z innymi pakietami

Jednak istnieje mała sztuczka:

6.6.2 Szczegóły dotyczące chronionego dostępu

Dostęp do chronionego elementu lub konstruktora obiektu można uzyskać spoza pakietu, w którym deklarowany jest tylko kod, który jest odpowiedzialny za jego realizację.

Oznacza to, że podklasa z innego pakietu nie może uzyskać dostępu protected członków dowolnych wystąpień ich superklas, mogą jedynie korzystać z nich na instancjami tego samego typu (gdzie typ to typ kompilacji wypowiedzi, ponieważ jest to kontrola kompilacji).

Na przykład (zakładając, że ten kod jest w Cat):

Dog dog = new Dog(); 
Animal cat = new Cat(); 

dog.testInstanceMethod(); // Not allowed, because Cat should not be able to access protected members of Dog 
cat.testInstanceMethod(); // Not allowed, because compiler doesn't know that runtime type of cat is Cat 

((Cat) cat).testInstanceMethod(); // Allowed 

Ma to sens, ponieważ dostęp z protected członków Dog przez Cat może złamać niezmienniki Dog, natomiast Cat mogą uzyskać dostęp do własnych protected członków bezpiecznie, ponieważ wie, jak zapewnić sobie własne niezmienniki.

Szczegółowe zasady:

6.6.2.1 Dostęp do chronionego Członek

Niech C będzie klasa, w którym chroniony członek m jest zadeklarowana. Dostęp jest dozwolony tylko w obrębie korpusu podklasy S C. Ponadto, jeśli identyfikator oznacza pole sposób wystąpienia lub wystąpienie, a następnie:

  • Jeżeli dostęp jest przez nazwę Q.Id kwalifikowaną, w którym Q oznacza Nazwa ExpressionName, wtedy dostęp jest dozwolony wtedy i tylko wtedy, gdy typ wyrażenia Q jest S lub podklasa S.
  • Jeśli dostęp jest przez wyrażenie dostępu do pola E.Id, gdzie E jest wyrażeniem Podstawowym, lub przez wyrażenie wywołania metody E.Id (...), gdzie E jest wyrażeniem pierwotnym, wówczas dostęp jest dozwolony wtedy i tylko wtedy, gdy typ E jest S lub podklasa S.

6.6.2.2 Kwalifikowany dostęp do chronionych Constructor

Niech C będzie klasa, w którym chroniony jest zadeklarowany konstruktor i niech S będzie najgłębsza klasa w której deklaracja wykorzystanie chronionego konstruktora występuje. Następnie:

  • Jeśli dostęp jest przez konstruktora nadklasy wywołania Super lub przez wykwalifikowanego konstruktora nadklasy wezwaniem E.super formy, gdzie E jest podstawowym wyrazem, a następnie (...) (...) dostęp jest dozwolony.
  • Jeśli dostęp polega na wywołaniu anonimowej klasy instancji, utworzeniu nowego formularza C (....) {...} lub przez utworzenie klasy kwalifikacyjnej, utworzenie formularza E.new C (..) { ...}, gdzie E jest podstawowym wyrażeniem, wtedy dostęp jest dozwolony.
  • W przeciwnym razie, jeśli dostęp jest spowodowany przez proste utworzenie klasy, wyrażenie formularza w postaci nowej C (..) Lub przez kwalifikowane wystąpienie klasy wystąpienie formularza E.new C (..), Gdzie E jest Wyrażenie podstawowe, wtedy dostęp jest niedozwolony. Do chronionego konstruktora można uzyskać dostęp za pomocą wyrażenia tworzenia instancji klasy (które nie deklaruje klasy anonimowej) tylko z poziomu pakietu, w którym jest zdefiniowany.

Zobacz także:

+0

Myślę, że ja zrozumiałe, ale wciąż potrzebuję czasu na jej przetrawienie i przebicie. kiedy nadpisujemy, czy musimy zachować sygnaturę metody, łącznie z modyfikatorami dostępu? Wydaje się, że jeśli superklasa ma 'protected void get() {}' i podklasa, która nadpisuje to nie może mieć 'void get() {}' , tzn. domyślny dostęp. ale może mieć 'public void get() {}' lub 'protected void get() {}' – eagertoLearn

+2

@eagertoLearn - Ideą tego jest to, że podklasa zawsze może uczynić metody bardziej dostępnymi, ale nie mniej dostępnymi; w ten sposób podklasa nadal jest zgodna z umową super-klasy. Mówiąc to w inny sposób, rzucanie do super-klasy nigdy nie powinno dać ci dostępu do większej liczby metod. –

0

Został utworzony instancję Cat i oddać go do typu Super klasa tzn typu Zwierząt. Zgodnie z typem zwierząt jego testInstanceMethod jest widoczny w tym samym pakiecie lub podtypach. Jeśli nie zostałbyś rzucony do typu Animal, kod się skompiluje.

nadzieję, że pomoże

./Arun

1

W Protected Access członkowie są dostępne w tym samym opakowaniu i za odziedziczone członek klasy w innym opakowaniu można również uzyskać.

Dostęp do pakietu umożliwia dostęp do członków klas w tym samym pakiecie. Członkowie klasy w innych pakietach nie mogą uzyskać dostępu w dostępie do pakietu.

+2

To pytanie ma już ponad trzy lata z zaakceptowaną odpowiedzią. Twoja odpowiedź również nie dodaje nic wartościowego do już zaakceptowanej odpowiedzi, więc nie widzę sensu twojej odpowiedzi tutaj (bez urazy). – rayryeng

+1

Czytanie "zaakceptowanej odpowiedzi" sprawiło, że moje oczy krwawią ... Nie jestem prawnikiem składni języka (i nie gram w telewizji), więc naprawdę doceniam tę "bardziej zwięzłą" odpowiedź. – geowar

Powiązane problemy