Одна защищенная переменная доступна, а другая нет.Зачем? - PullRequest
2 голосов
/ 17 марта 2019

Это вопрос защищенного наследования.Я понимаю, что защищенный означает, что в пакете он как бы публичный.Вне пакета, вообще говоря, он доступен только тогда, когда вы ВНУТРИ подкласса.Это не мое замешательство.Моя путаница связана с небольшим появлением гниды, и я не знаю почему.Я объясню суть вопроса после кода.Вам предоставляются пакеты com.wobble.foo, который содержит класс TestA, и com.wobble.bar, который содержит класс TestB, расширяющий класс A.

//A Package
package com.wobble.foo;

public class TestA{
    static protected int x = 5;
    protected int y = 6;
}

//A different Package
package com.wobble.bar;

public class TestB extends TestA{
    static{
        TestA t = new TestA();
        t.x = 1; //compiles
        t.y = 2; //field not visible, fails to compile
    }
}

Суперкласс имеет две защищенные переменные, одна статическая,Подкласс в другом пакете создал новый объект суперкласса, пытающийся получить доступ к этим двум переменным.Почему вы можете через объект получить доступ к статической переменной через него, но не получить доступ к переменной экземпляра через него?Они оба защищены.Оба из одного класса.Оба получают доступ к одному и тому же объекту.Обратите внимание, тем, кто считает, что это может быть дубликатом: другие вопросы просто спрашивают, как работает защищенный, но они не задают конкретный вопрос о том, почему доступна только одна из этих двух переменных, обе из которых защищены.

-Спасибо

PS:

Это не вопрос как исправить код.Я знаю, как заставить конец игры работать.Вопрос в том, почему он доступен через t.x;, а не t.y;?

1 Ответ

2 голосов
/ 17 марта 2019
 t.x = 1; //compiles

Это поле static.Поэтому вы должны написать это как TestA.x (об этом будет предупреждение компилятора).

Статические защищенные поля доступны из статического кода подклассов (или из нестатического кода в этом отношении).

 t.y = 2; //field not visible, fails to compile

Это поле экземпляра.Защищенные поля экземпляра доступны из методов экземпляра на подклассах.Но только изнутри этих методов.Вы не можете вызывать их из статического метода (даже если этот статический метод находится в подклассе).

Если вам нужно получить доступ к полям из статического метода в другом классе, вам нужно либо создать полеpublic или переместите код, который нуждается в нем, в тот же пакет.


Но только изнутри этих методов.

И только если вы можете быть уверены, чторассматриваемый экземпляр фактически из вашего собственного класса.

В вашем примере

TestA t = new TestA();
t.y = 2;

t.y не отображается, потому что код в TestB не может получить доступ к защищенному полю в экземплярах TestA. Это должен быть экземпляр TestB.Однако тот же код будет работать внутри метода на TestA.

Также не будет работать следующее:

// in TestB
void boo(TestA someInstance){
   this.y = someInstance.y; 
   // does not compile, because someInstance.y is not visible
   // because it could be from unknown TestC
}

Хорошо, что имеет смыслно тогда как я могу получить доступ к TX?Это тоже защищенный член, и я все еще не т.

Экземпляр t здесь вообще не используется (это может быть , может быть даже null и кодвсе равно будет работать).Статический метод отправляется только для типа переменной (объявленного) во время компиляции.В идеале t.x даже не должно быть разрешено , но по крайней мере вы получаете предупреждение компилятора.


это статично, так что технически вы не получаете к нему доступ черезсуперкласс, но через подкласс?ietx -> x -> TestB.x, который получает его через TestB?

Статические методы не могут быть переопределены подклассами.TestB.x - это просто сбивающий с толку (или удобный, в зависимости от того, как вы на это смотрите) способ написания TestA.x.Вы можете думать об этом как о подклассе, автоматически импортирующем все (публичные и защищенные) статические поля и переменные из родительского класса.Делает меньше нажатий клавиш, но не меняет поведение (конечно, работает очень отличается от методов экземпляра, которые динамически отправляются на фактический тип экземпляра).

В любом случае, поскольку TestA.x защищен, он доступенк статическим кодовым блокам в подклассах TestA, включая TestB.

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