Переопределение защищенных методов в 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()
в B
суперклассе.
Приветствуются ссылки на соответствующую часть JLS.
Ответы
Ответ 1
Здесь вы переходите к JLS в ключе protected
:
JLS protected description и JLS protected example.
В основном модификатор protected
означает, что вы можете получить доступ к полю/методу/... 1) в подклассе данного класса и 2) из классов в том же пакете.
Из-за 2) new A().test()
работает. Но new B().test()
не работает, потому что класс B
находится в другом пакете.
Ответ 2
Это не так, как наследование работает на Java.
Если метод переопределен, а переопределенный метод не отображается, это ошибка времени компиляции, чтобы попытаться вызвать его.
Кажется, вы ожидаете, что Java автоматически вернется к методу суперкласса, но этого не произойдет.
Я попытаюсь выкопать JLS позже, почему это не сделано...
Ответ 3
Проблема заключается в том, что во время компиляции вы сообщаете Java, что хотите получить доступ к защищенному члену класса, когда у вас нет такого доступа.
Если вы это сделали,
A a = new B();
a.test();
Затем он будет работать, и переопределенный метод будет запущен, потому что во время компиляции Java проверяет, что у вас есть доступ к A. Во время выполнения предоставленный объект имеет соответствующий метод, поэтому выполняется метод B(). Динамическое связывание или поздняя привязка - это ключ.
Ответ 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