переопределение переменной в Java - PullRequest
0 голосов
/ 01 февраля 2012
public class Foo {
      public int a = 3;
    public void addFive(){
        a += 5; System.out.print("f ");
    }
}

public class Bar extends Foo {
    public int a = 8;
    public void addFive(){ 
        this.a += 5; 
        System.out.print("b " ); 
    }
}

public class Test {
    public static void main(String args[]){
        Foo f = new Bar(); 
        f.addFive();
        System.out.println(f.a);
    }
 }

Я получаю вывод b 3. Почему он не выдает b13 в качестве вывода. Может кто-нибудь объяснить, пожалуйста.

Ответы [ 4 ]

4 голосов
/ 01 февраля 2012

Предполагается, что класс Foo объявлен как показано ниже

class Foo 
{

    public int a = 3;

    public void addFive()
    { 
        a += 5; 
        System.out.print("f ");
    }
}
  1. Переменные не имеют понятия переопределения. Они просто замаскированы.
  2. Это печать 3, потому что, когда вы используете ссылку на суперкласс для доступа к переменной, она обращается к переменной, объявленной только в суперклассе. Помните, что суперкласс ничего не знает о подклассе.
0 голосов
/ 01 февраля 2012

Я предполагаю, что вы хотели объявить целочисленное поле a в классе Foo.

Ответ на ваш вопрос связан с понятиями «переопределение» и «сокрытие», как это делают другиеуказал.Другой способ объяснить это состоит в том, что для переменных-членов не существует такого понятия, как «динамическая диспетчеризация».Это означает, что если вы обращаетесь к члену определенного объекта, система проверяет во время выполнения , какой элемент вы имеете в виду, просматривая иерархию классов.

Итак, при вызовеметод f.addFive, во время выполнения система увидит, что ваш объект на самом деле Bar, а не Foo, и поэтому возьмите функцию addFive, которую вы определили в классе Bar.

Этого не происходит с переменными-членами: вы обращаетесь к f.a в своем операторе печати, и во время компиляции решается, что прямо здесь вы хотите получить доступ к полю a, объявленному в классеFoo там - и вот, это то, что произойдет во время выполнения.

Теперь, причина , что отсутствует динамическая диспетчеризация для доступа к переменной-члену, - это производительность: это будеточень дорого обходить всю логику «посмотрите, что это за объект на самом деле» каждый раз, когда вы просто хотите добавить какое-то значение в переменную-член.

0 голосов
/ 01 февраля 2012
class Foo {
        public void addFive() { 
            a += 5; System.out.print("f "); 
        }
}

у вас не определена переменная 'a', поэтому этот пример даже не компилируется.

правильный код:

class Foo {

       public int a;

       public void addFive() { 
          a += 5; System.out.print("f "); 
       }
}

и см. Ссылку https://stackoverflow.com/a/2464254/1025312

0 голосов
/ 01 февраля 2012

Объявление public int a = 8 в классе Foo вместо Bar класса должно работать ... печать B 3 .

Но я полагаю, вы говорите о включенном вопросев сертификационном экзамене по Java, поэтому вы должны исправить код класса Foo, добавив public int a = 3.

Вы не можете переопределить переменную в Java, но объявив ее как public (или protected).) в суперклассе вы можете использовать его также во всех унаследованных классах.

В этом случае правильный вывод будет B 13 , потому что в тестовом классе вы находитесьиспользуя объект Bar в качестве объекта Foo, поэтому значение a равно 3 , а не 8 .

...