Вопрос
У меня только что есть странная ошибка, которая включает в себя защищенный модификатор.
У меня есть следующий код:
package p1;
public class C1 {
protected void doIt() {}
}
package p2;
public class C2 extends p1.C1 {
private C1 c1_instance;
public void doItAgain() {
c1_instance.doIt(); // wtf!!!!
}
}
Я получаю ошибку, заявляя, что doIt()
Защищенный доступ и не может быть доступен! Но я нахожусь в подклассном классе и имею и доступ к doIt()
метод
Разве это не ошибка?
Решение
У меня также было впечатление, что protected
означал «доступный из того же пакета или из подкласса», но Язычная спецификация Конечно, более точнее и объясняет, что в подклассе S, «если доступ к квалифицированному имени Q.ID, где Q является именем выражения, то доступ разрешен тогда и только тогда, когда тип выражения Q S или подкласс S. "
Таким образом, вы можете только получить доступ к protected
Метод суперкласса посредством ссылки на подкласс, из которого вы звоните, например:
public class C2 extends C1 {
private C2 c2_other_instance;
public void doItAgain() {
c2_other_instance.doIt();
}
}
Если вы объясните, почему вы хотите получить доступ к одному экземпляру SuperClass из другого экземпляра подкласса, то кто -то может предложить лучший дизайн. В противном случае вам придется сделать метод public
или поместите классы в тот же пакет.
Другие советы
В Java вы не можете позвонить protected
методы В другом случае базового класса, даже из подкласса:
public class C2 extends p1.C1 {
private C1 c1_instance;
public void doItAgain() {
doIt(); // fine
c1_instance.doIt(); // disallowed
}
}
Единственное исключение - это когда базовый класс и подкласс находятся в одном пакете.
To quote the Java OO Учебное пособие:
А
protected
Модификатор указывает, что к участнику можно получить доступ только в своем собственном пакете (как в случае с Package Provate) и, кроме того, подклассом своего класса в другом пакете.
Защитный эквивалентен доступу к уровню упаковки; Вы не можете получить доступ к методу, если вы находитесь в другом пакете.
Вы должны иметь возможность вызвать doit () непосредственно, не проходя через объект C1_Instance, так как C2 является подклассом.
Из http://download.oracle.com/javase/tutorial/java/javaoo/accesscontrol.html
«Защищенный модификатор указывает, что к члену можно получить доступ только в своем собственном пакете (как в случае с Package Private) и, кроме того, подклассом своего класса в другом пакете».
C2 может быть подкладом C1, но это не означает, что он может получить доступ к этим методам в другом случае, то есть C1_Instance не может быть экземпляром C2. Вы можете получить доступ к нему, если бы он был в том же пакете.
Нет, protected
обеспечивает доступ в той же пакете и в уроках потомков. Вы не находитесь ни в одном и том же пакете, и не обращаетесь к нему непосредственно из урока потомков. C2
Потомок, но c1_instance
не.
Если ваш метод объявлен защищенным, вы можете получить доступ к этому в этом классе, без пакета и в рамках подкласса.
Теперь вот вопрос, почему есть ошибка, несмотря на доступ к этому защищенному участнику из его подкласса. Ответ состоит в том, чтобы получить доступ к защищенному методу из подкласса, который ваш подкласс должен использовать метод непосредственно из прямого подкласса. Здесь прямой подкласс - C2, но экземпляр C1_Instance нет. Вы можете использовать этот метод напрямую (doit () вместо c1_instance.doit ())