Java: наследование, переменные экземпляра и это - PullRequest
1 голос
/ 29 сентября 2011

Я понял, что this является ссылкой на текущий выполняемый объект.Если это так, можете ли вы объяснить поведение следующего кода?

public class Inherit {

    public static class ClassA
    {
        private String privateInstanceVar = "Private";
        public void classAMethod()
        {
            System.out.println("In class: " + this.getClass().getName());
            System.out.println("Can access: " + this.privateInstanceVar);
        }
    }

    public static class ClassB extends ClassA
    {
    }

    public static void main(String[] args)
    {
        ClassB b = new ClassB();
        b.classAMethod();
        //Outputs:
        //In class: Inherit$ClassB
        //Can access: Private

        //System.out.println(b.privateInstanceVar); // Fails to compile
    }   
}

Первая строка classAMethod сообщает, что this является ссылкой на ClassB.Однако в следующей строке я использую this для доступа к закрытой переменной экземпляра privateInstanceVar из ClassA, к которой у меня не должно быть доступа.(Закомментированная последняя строка main показывает, что это действительно так.)

Итак, мои вопросы:

  1. Если this действительно является ссылкой на ClassB, как я могу получить доступ к закрытой переменной экземпляра на ClassA из метода, который принадлежит ClassB?
  2. Является ли classAMethod на самом деле членом ClassA и ClassB в точке исполнения?
  3. Если ответ на вопрос 2. да, каковы правила определения того, в каком контексте будет выполняться любая строка в методе?
  4. Если ответ на вопрос 2. нет, то чтоЕсть ли альтернативное объяснение поведению кода?
  5. Есть ли здесь какая-то большая картина или тонкость, которую я не могу оценить?

Ответы [ 5 ]

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

Если это действительно ссылка на ClassB, как я могу получить доступ к переменная экземпляра в ClassA из метода, который принадлежит ClassB?

Поскольку вы наследуете метод от classA, и этот метод обращается к закрытой переменной.

Является ли classAMethod на самом деле членом ClassA и ClassB в точке исполнение

Да

Если ответ на вопрос 2. да, каковы правила определения в какой контекст будет выполнять любая строка в методе?

Контекст времени компиляции: будет выбран метод или поле, видимые из кода, который вы пишете. Пример:

public static class ClassA{
    private String foo = "bar";
    public String getFoo(){return foo;}
}
public static class ClassB extends ClassA{
    private String foo = "phleem";
}

new ClassB().getFoo() вернет "bar", а не "phleem", потому что ClassA не знает о ClassB.

3 голосов
/ 29 сентября 2011

Я не уверен, в чем причина вашего замешательства. Он работает точно так, как и следовало ожидать:

Подкласс не наследует частные члены своего родительского класса. Однако, если у суперкласса есть открытые или защищенные методы для доступа к его частным полям, они также могут использоваться подклассом.

http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html

1 голос
/ 29 сентября 2011
  1. Да, this относится к экземпляру ClassB, который также является экземпляром ClassA.Метод classAMethod определен в ClassA и, следовательно, имеет доступ ко всем закрытым элементам ClassA.
  2. Да, classAMethod - это метод ClassA, унаследованный ClassB
  3. Строка выполняется в контексте класса, в котором определена эта строка.
  4. Не применимо
0 голосов
/ 29 сентября 2011

ClassB имеет доступ к classAMethod(), но не имеет доступа к privateInstanceVar.Поэтому, если вы попытаетесь переопределить classAMethod() или даже определить какой-либо другой метод, который попытается получить доступ к privateInstanceVar, вы получите ошибку.Для этого переменная должна быть объявлена ​​защищенной.

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

1) Поскольку ClassB наследуется от ClassA, все общедоступные защищенные методы ClassA видны экземпляру ClassB.

2) Да.

3) если вы не переопределите classAMethod в ClassB, ClassB просто выполнит CLassA.classAMethod ()

5) Это нормальный способ наследования, работающий в Java.

...