Java защищенный модификатор - PullRequest
3 голосов
/ 08 сентября 2011

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

У меня есть следующий код:

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().

Разве это не ошибка?

Ответы [ 6 ]

4 голосов
/ 08 сентября 2011

У меня также сложилось впечатление, что protected означает «доступный из того же пакета или из подкласса», но Спецификация языка Java , конечно, более точна и объясняет, что в подклассе S из C , «Если доступ осуществляется по полному имени Q.Id, где Q - ExpressionName, тогда доступ разрешается тогда и только тогда, когда тип выражения Q - S или подкласс S».

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

public class C2 extends C1 {
    private C2 c2_other_instance;
    public void doItAgain() {
        c2_other_instance.doIt();
    }
}

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

2 голосов
/ 08 сентября 2011

В Java нельзя вызывать protected методы для другого экземпляра базового класса , даже из подкласса:

public class C2 extends p1.C1 {
    private C1 c1_instance;
    public void doItAgain() {
        doIt();             // fine
        c1_instance.doIt(); // disallowed
    }
}

Единственное исключение - это когда базовый класс и подкласс находятся в одном пакете.

Цитировать Учебник Java OO :

Модификатор protected указывает, что доступ к элементу возможен только в своем собственном пакете (как с пакетом private) и, кроме того, подкласс этого класса в другом пакете.

1 голос
/ 08 сентября 2011

Нет, protected обеспечивает доступ в том же пакете и в классах-потомках. Вы не находитесь ни в одном и том же пакете и не обращаетесь к нему напрямую из класса-потомка. C2 является потомком, но c1_instance не является.

1 голос
/ 08 сентября 2011

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

1 голос
/ 08 сентября 2011

Защищено эквивалентно доступу на уровне пакета; вы не можете получить доступ к методу, если вы находитесь в другом пакете.

Вы должны иметь возможность вызывать doIt () напрямую, не проходя через объект c1_instance, поскольку C2 является подклассом.

С http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

"Защищенный модификатор указывает, что доступ к члену возможен только в его собственном пакете (как в случае с package-private) и, кроме того, с помощью подкласса его класса в другом пакете."

0 голосов
/ 08 сентября 2011

Если ваш метод объявлен защищенным, вы можете получить к нему доступ в этом классе, в пакете и в подклассе.

Теперь возникает вопрос, почему возникает ошибка, несмотря на доступ к этому защищенному члену из его подкласса.Ответ заключается в том, чтобы получить доступ к защищенному методу из подкласса. Ваш подкласс должен использовать метод непосредственно из прямого подкласса.здесь прямым подклассом является C2, а экземпляром c1_instance - нет.Вы можете использовать этот метод напрямую (doIt () вместо c1_instance.doIt ())

...