Есть ли способ получить доступ к конкретным значениям переменных класса из конкретных методов абстрактного класса - PullRequest
1 голос
/ 10 апреля 2019

У меня есть понимание скрытия переменных и переопределения методов и виртуальных методов, вызывающих в Java. Мой вопрос: почему скрытие переменных не действует в унаследованных методах? Означает ли это, что мы должны переопределить методы, которые обращаются к этим переменным в каждом дочернем классе?

Абстрактный класс

public abstract class ClassA{

    protected int i = 0;

    public void printOurStuff(){
        System.out.println(i);
    }

    public void printMyStuff(){
        System.out.println(this.i);
    }

    public void printSomeStuff(String s){
        System.out.println(s);
    }

}

Класс бетона

 public class ClassB extends ClassA{

     protected int i = 1;

     public static main(String[] args){
         ClassB b = new ClassB();
         b.printOurStuff();
         b.printMyStuff();
         b.printSomeStuff(b.i);
     }

 }

Результаты

0 0 1 * * тысяча двадцать-один

РЕДАКТИРОВАТЬ - изменил модификатор доступа для поля с частного на защищенный и добавил метод printOurStuff

1 Ответ

2 голосов
/ 10 апреля 2019

Когда вы объявляете приватные поля, такие как

  private int i = 0;

это означает, что только этот конкретный класс может получить доступ к этой переменной. Это поле недоступно для подклассов. Если вы хотите, чтобы это поле было доступно для подклассов, вы должны сделать его protected вместо:

  protected int i = 0;

Чтобы переопределить значение этого поля, вы можете использовать статический блок, например:

public class ClassB extends ClassA {
    {
         i = 1;
    }
}

или присвойте новое значение в конструкторе:

public class ClassB extends ClassA {
     public ClassB() {
         i = 1;
     }
}

Что касается вашего примера, если вы осмотрите объект ClassB с помощью отладчика, вы обнаружите, что на самом деле у вас есть два поля i: одно для ClassA и одно для ClassB.

UPDATE:

Что касается случая, когда переменная i равна protected:
Посмотрите внимательно на определение ваших классов.
Вы не можете не согласиться с тем, что вы объявляете i поле два раза: для ClassA и ClassB. JVM будет уважать это заявление и следовать вашим инструкциям. Если поле protected или даже public, у вас все еще есть два поля. Вы не можете просто переопределить их, как вы переопределяете методы. И при доступе к полю, подобному i = ..., вы фактически получаете доступ к ближайшему полю вашей области. Для ClassB это его поле i, а не поле его суперкласса ClassA.

Также вы можете получить доступ к полю суперкласса следующим образом:

super.i = ...

super является ссылкой на суперкласс.

...