Подтвердить что ты не робот

Разница между защищенными и модификаторами доступа к частному доступу в Java?

Я видел различные статьи о различиях между защищенными и частными модификаторами пакета. Одна вещь, которую я нашел противоречивой между этими двумя сообщениями

Разве они не противоречат друг другу? из моего понимания других статей, первое сообщение дает правильный ответ, который защищает == package-private + подкласс в другом пакете.

Если это утверждение верно, то почему этот код не работает со следующим сообщением об ошибке в моем подклассе Cat по строке 17

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

мой код для супер и подкласс ниже.

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();
        }
    }

Просьба пояснить, почему приведенный выше код не работает. Это было бы очень полезно. Благодаря

4b9b3361

Ответ 1

Первый ответ в основном правильный - protected доступ к элементам осуществляется

  • классы из одного пакета
  • подклассы класса объявления из других пакетов

Однако есть небольшой трюк:

6.6.2 Сведения о защищенном доступе

Защищенный член или конструктор объекта может быть доступен извне пакета, в котором он объявляется только кодом, ответственным за реализацию этого объекта.

Это означает, что подкласс из другого пакета не может получить доступ к protected членам произвольных экземпляров своих суперклассов, они могут обращаться к ним только в экземплярах своего собственного типа (где type - это тип выражения типа компиляции, поскольку он компилируется проверка времени).

Например (предполагая, что этот код находится в 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

Это имеет смысл, поскольку доступ к protected членам Dog на Cat может привести к поломке инвариантов Dog, тогда как Cat может безопасно получить доступ к своим protected членам, поскольку он знает, как обеспечить его собственные инварианты.

Подробные правила:

6.6.2.1 Доступ к защищенному члену

Пусть C - класс, в котором объявлен защищенный член m. Доступ разрешен только внутри тела подкласса S of C. Кроме того, если Id обозначает поле экземпляра или метод экземпляра, то:

  • Если доступ осуществляется по квалифицированному имени Q.Id, где Q - имя ExpressionName, то доступ разрешен тогда и только тогда, когда тип выражения Q является S или подклассом S.
  • Если доступ осуществляется с помощью выражения доступа к полю E.Id, где E является первичным выражением или выражением вызова метода E.Id(...), где E является первичным выражением, доступ разрешен тогда и только тогда, когда тип E является S или подклассом S.

6.6.2.2 Квалифицированный доступ к защищенному конструктору

Пусть C - класс, в котором объявлен защищенный конструктор, и пусть S - самый внутренний класс, в объявлении которого используется использование защищенного конструктора. Тогда:

  • Если доступ осуществляется вызовом конструктора суперкласса super (...) или квалифицированным конструктором конструктора суперкласса формы E.super(...), где E является первичным выражением, тогда доступ разрешен.
  • Если доступ является выражением создания экземпляра анонимного класса формы new C (...) {...} или выражением для экземпляра квалифицированного экземпляра класса E.new C (...) {...}, где E - первичное выражение, доступ разрешен.
  • В противном случае, если доступ осуществляется с помощью простого экземпляра экземпляра экземпляра экземпляра формы new C (...) или выражения выражения экземпляра квалифицированного класса формы E.new C (...), где E Первичное выражение, тогда доступ не разрешен. Доступ к защищенному конструктору можно получить с помощью выражения создания экземпляра класса (которое не объявляет анонимный класс) только из пакета, в котором он определен.

См. также:

Ответ 2

В защищенном доступе доступ к элементам осуществляется в одном пакете, а для наследуемого члена класса в другом пакете также можно получить доступ.

В доступе пакета доступ к элементам классов в одном пакете возможен. К членам класса в других пакетах нельзя получить доступ в пакетном доступе.

Ответ 3

Вы создали экземпляр Cat и применили его к типу суперкласса типа i.e. Animal. По типу Animal его testInstanceMethod отображается в том же пакете или подтипах. Если вы не указали тип Animal, код будет скомпилирован.

Надеюсь, что поможет

./Arun