różnica między modyfikatorami protected i package-private access w Javie? [duplikat]

To pytanie ma już odpowiedź tutaj:

Widziałem różne artykuły na temat różnic między modyfikatorami protected i package private. Jedna rzecz znalazłem sprzeczne między tymi dwoma postami

  1. Nie jest "package private" member access jest synonimem domyślnego (bez modyfikatora) dostępu?

    W tym zaakceptowana odpowiedź mówi, że

    Modyfikator protected określa, że członek może być dostępny tylko w jego własnym pakiecie (tak jak w pakiecie-private), a dodatkowo przez podklasę jego klasy w innym pakiecie.

  2. Dlaczego modyfikator protected zachowuje się inaczej w podklasie Java?

    W tym zaakceptowana odpowiedź mówi że

    Aby zapewnić dostęp na poziomie chronionym, muszą być spełnione dwa warunki:

    • klasy muszą być w tym samym pakiecie.
    • musi istnieć związek dziedziczenia.
Czy nie są sprzeczne? z mojego zrozumienia innych artykułów, pierwszy post daje poprawną odpowiedź, że protected = = pakiet-prywatna + podklasa w innym pakiecie.

Jeśli to stwierdzenie jest poprawne, to dlaczego ten kod nie działa z following error message on my subclass Cat on line 17

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

Mój kod dla 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 działa. To byłoby bardzo przydatne. Dzięki

Author: Community, 2013-08-28

3 answers

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

  • klasy z tego samego pakietu
  • podklasy klasy deklarującej z innych pakietów

Jest jednak mała sztuczka:

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

Chroniony element lub konstruktor obiektu może być dostępny spoza pakietu, w którym jest zadeklarowany tylko przez kod odpowiedzialny za implementacja tego obiektu.

Oznacza to, że podklasa z innego pakietu nie może uzyskać dostępu do członków protected arbitralnych instancji ich superklas, mogą uzyskać do nich dostęp tylko na instancjach własnego typu (gdzie type jest wyrażeniem typu compile-time, ponieważ jest to sprawdzenie w czasie 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 do protected członków Dog przez Cat może złamać niezmienniki Dog, podczas gdy {[3] } może bezpiecznie uzyskać dostęp do swoich członków protected, ponieważ wie, jak zapewnić własne niezmienniki.

Szczegółowe zasady:

6.6.2.1 dostęp do chronionego członka

Niech C będzie klasą, w której deklarowany jest chroniony element M. Dostęp jest dozwolony tylko w ciele podklasy S of C. Dodatkowo, jeśli Id oznacza pole instancji lub metodę instancji, to:

  • Jeśli dostęp jest przez kwalifikowaną nazwę Q.Id, gdzie Q jest Nazwa wyrażenia, wtedy dostęp jest dozwolony wtedy i tylko wtedy, gdy typem wyrażenia Q Jest S lub podklasa S.
  • jeśli dostęp jest wyrażeniem dostępu do pola E.Id, gdzie E jest wyrażeniem podstawowym, lub metodą wywołania wyrażenia E.Id ( ... ) .), gdzie E jest wyrażeniem podstawowym, wtedy dostęp jest dozwolony wtedy i tylko wtedy, gdy typem E jest S lub podklasa S.

6.6.2.2 kwalifikowany dostęp do chronionego konstruktora

Niech C będzie klasa, w której deklarowany jest chroniony konstruktor i niech s będzie najbardziej wewnętrzną klasą, w której deklaracji użycie chronionego konstruktora ma miejsce. Następnie:

  • jeśli dostęp jest przez konstruktor superclass invocation super(. . .) lub przez wykwalifikowanego konstruktora superklasycznego wywołania postaci E. super(. . .), gdzie E jest wyrażeniem podstawowym, wtedy dostęp jest dozwolony.
  • jeśli dostęp jest przez anonimowe wyrażenie tworzenia instancji klasy w postaci new C (. . .){...} lub przez kwalifikowane wyrażenie tworzenia instancji klasy w postaci E. new C(. . .){...}, gdzie E jest wyrażeniem podstawowym, wtedy dostęp jest dozwolony.
  • W przeciwnym razie, jeśli dostęp jest przez proste wyrażenie tworzenia instancji klasy w postaci new C (. . .) lub przez kwalifikowane wyrażenie tworzenia instancji klasy w postaci E. new C(. . .), gdzie E jest wyrażeniem podstawowym, wtedy dostęp nie jest dozwolony. Do chronionego konstruktora można uzyskać dostęp za pomocą wyrażenia tworzenia instancji klasy (nie deklaruje anonimowej klasy) tylko z pakietu, w którym jest zdefiniowana.

Zobacz też:

 24
Author: axtavt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-28 18:24:22

W protected access członkowie są dostępni w tym samym pakiecie, a dla dziedziczonego członka klasy w innym pakiecie również mogą być dostępni.

W pakiecie access można uzyskać dostęp do członków klas w tym samym pakiecie. Członkowie klasy w innych pakietach nie mogą być dostępni w pakiecie access.

 2
Author: Muhammad kazmi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-10 18:45:48

Stworzyłeś instancję kota i wrzuciłeś ją do super klasy, tj. typu zwierzęcia. Zgodnie z typem zwierzęcia jego testInstanceMethod jest widoczny w tym samym opakowaniu lub dowolnym podtypie. Jeśli nie wrzuciłeś do Animal wpisz kod zostanie skompilowany.

Hope that helps

./ Arun

 0
Author: Arun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-28 18:28:00