Переопределение защищенных методов в Java

#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