#java #methods #overriding #protected
#java #методы #переопределение #защищенный
Вопрос:
Test.java
package a;
import b.B;
public class Test {
public static void main(String[] v) {
new A().test();
new B().test();
}
}
A.java:
package a;
public class A {
protected void test() { }
}
B.java:
package b;
public class B extends a.A {
protected void test() { }
}
Почему new B().test()
выдает ошибку? Разве это не нарушает правила видимости?
B.test()
невидимо в Test
, потому что они находятся в разных пакетах, и все же оно отказывается вызывать суперкласс test()
in B
, который является видимым.
Ссылки на соответствующую часть JLS были бы оценены.
Комментарии:
1. «выдает ошибку» .. Вы можете быть более конкретными?
2. @Kevin он спрашивает, почему он не может вызвать метод, к которому у него есть доступ к superметоду.
3. @Jeremy: он отказывается компилироваться: «a/Test.java:10: test() имеет защищенный доступ в b.B»
4. @Kevin: Прочитайте вопрос: «разве это не нарушает правила видимости?»
5. @Jeremy ошибка (в данном случае) довольно очевидна: это ошибка времени компиляции, в которой говорится, что
B().test()
она не виднаa.Test.main(String[])
.
Ответ №1:
Вот вам JLS по protected
ключевому слову: описание защищенного JLS и пример защищенного JLS.
По сути, protected
модификатор означает, что вы можете получить доступ к полю / методу / … 1) в подклассе данного класса и 2) из классов в том же пакете.
Из-за 2) new A().test()
работает. Но new B().test()
не работает, потому что класс B
находится в другом пакете.
Ответ №2:
Проблема в том, что во время компиляции вы сообщаете Java, что хотите получить доступ к защищенному члену класса, когда у вас нет такого доступа.
Если бы вы сделали это вместо;
A a = new B();
a.test();
Тогда это сработает, и переопределенный метод будет запущен, потому что во время компиляции Java проверяет, есть ли у вас доступ к A. Во время выполнения предоставленный объект имеет соответствующий метод, поэтому выполняется метод B test(). Ключом является динамическое связывание или позднее связывание.
Ответ №3:
Это просто не то, как работает наследование в Java.
Если метод переопределен, а переопределенный метод не виден, попытка его вызова является ошибкой времени компиляции.
Кажется, вы ожидаете, что Java автоматически вернется к методу в суперклассе, но этого не происходит.
Позже я попытаюсь разобраться в JLS, почему это не сделано…
Ответ №4:
Да, переопределение защищенного метода возможно.
class A{
protected void f(){
SOP("A");
}}
class B extends A{
protected void f(){
SOP("B");
}
public static void main(String...args)
{
B b=new B();
b.f();
}
}
Вывод: B