Не может получить доступ к защищенному члену в подклассе, который также является подклассом - PullRequest
3 голосов
/ 30 июля 2011

Это пример из Руководства программиста по сертификации Java ™ SCJP. Всеобъемлющий учебник - третье издание - Халид А. Могол Рольф В. Расмуссен , который я не могу понять.

Я знаю, что мы не можем получить доступ к защищенному члену, если не наследуем его в подкласс, определенный в другом пакете.

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

Пример следует

A.java

package packageA;
public class A {
    protected int z;
}

B.java

package packageB;

import packageA.A;

public class B extends A {

    void action(A obj1, B obj2, C obj3) {
        z = 10;      // z in B - Works
        obj1.z = 10; // Won't work for obvious reason
        obj2.z = 10; // z in B - Works
        obj3.z = 10; // z in C - Works

    }
}

class C extends B {

    void action(A obj1, B obj2) {
        z = 10; // Works
        obj1.z = 10; // Won't work for obvious reason
        obj2.z = 10; // z in B - WHY DOESN'T THIS WORK?????

    }
}

Ответы [ 2 ]

3 голосов
/ 20 марта 2014

В настоящее время принятый ответ не отвечает на вопрос.Это объясняет, почему вы не можете получить доступ к элементу z экземпляра A из тела B или C.Но возникает вопрос, почему вы не можете получить доступ к члену z экземпляра B из C.

Причина в том, что B не является подклассом C.Прочитайте спецификацию Java, раздел 6.6.2.1:

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

Кроме того, если Id обозначает поле экземпляра или метод экземпляра, то:

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

http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.2.1

(разметка)

Таким образом, в пределах B вы можете сказать obj3.z, потому что obj3 имеет тип C и C является подклассом B.

Но в пределах C вы не можете сказать obj2.z, потому что obj2 имеет тип B, а B - , а не aподкласс C.


Чтобы суммировать значение защищенного:

Предположим, что защищенный член объявлен в теле класса A.

(1) Доступ к защищенному члену можно получить из любого места в пакете, содержащем A.

(2) Кроме того, подкласс S из A, определенный в другомарендовать пакет, может получить доступ к защищенному члену в экземплярах S или экземплярах классов, которые наследуются от S, , но не в экземплярах классов, от которых S наследует.

Последнее предложение является ключевым моментом, когда речь идет об ответе на этот вопрос.

1 голос
/ 30 июля 2011

Защищенные члены могут только быть доступными для подклассов класса, в котором они объявлены или классов в том же пакете , что и класс, в котором объявлен защищенный член,Классы B и C в вашем случае объявлены в пакетах, отличных от класса A. Вот почему вы не можете получить доступ к 'z' через ссылку на класс A. Если вы переместили классы B и C в тот же пакет, что и A, этобуду работать.

Вот почему вы не можете получить доступ к obj2.z в классе C, так как 'z' объявлено в классе в другом пакете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...