2014-09-15 2 views
3
public class Circle { 
    public float r = 100; 
    public float getR() { 
     return r; 
    } 
} 

public class GraphicCircle extends Circle { 
    public float r = 10; 
    public float getR() { 
     return r; 
    } 

    // Main method 
    public static void main(String[] args) { 
     GraphicCircle gc = new GraphicCircle(); 
     Circle c = gc; 
     System.out.println("Radius = " + gc.r); 
     System.out.println("Radius = " + gc.getR()); 
     System.out.println("Radius = " + c.r); 
     System.out.println("Radius = " + c.getR()); 
    } 

} 

Привет, У меня возникли проблемы с пониманием вывода вышеприведенного кода. Выход:
Java-метод переопределения и переменной тенирования

Radius = 10.0 
Radius = 10.0 
Radius = 100.0 
Radius = 10.0 

Я понимаю, почему gc.r 10. Я также понять, почему gc.getR() 10 (так как метод GETR() в GraphicCircle переопределяет метод GETR() из Circle). Но я не понимаю, почему c.r - 100, а c.getR() - 10 (у меня возникают проблемы с пониманием того, что происходит в наследовании, когда вы приписываете класс предков, как это сделал код выше).

+2

Вот что вы хотите знать - http://stackoverflow.com/questions/9453701/what-is-virtual-method-calling-in-java – Betlista

+0

Возможный дубликат [Почему переменные не ведут себя так же, как метод while Overriding.?](http://stackoverflow.com/questions/17201227/why-variables-are-not-behaving-as-same-as-method-while-overriding) – Mikaveli

ответ

2

Вызов метода виртуальный в Java, что означает, что вызывается метод из фактического типа объекта, независимо от того, какой тип ссылки использовался для доступа к объекту. Прямой доступ к полям, с другой стороны, не является виртуальным, поэтому r вы будете зависеть от типа ссылки, через которую вы ее достигли.

+0

Спасибо, что прояснил это. – killuminati

4

Вы можете переопределить методы, а не поля или переменные класса. Таким образом, getR() переопределен и фактически отображает то, что вы ожидаете.

Получение c.r Вы получаете переменную класса окружения, а не GC.

Это также плохая привычка публиковать переменные класса. Они должны быть закрытыми или, по крайней мере, защищенными и доступными к ним с использованием геттеров и сеттеров (more about private fields).

2

Прежде всего, поле r не слежка, это скрытый.

Во-вторых, технический термин в отношении переопределяющих методов называется динамическое связывание. Это просто означает, что во время выполнения проверяются фактический класс экземпляра при поиске метода, который вызывается.

С другой стороны, для полей мы имеем статическое связывание. Это означает, что компилятор уже разрешает все обращения к полю, и компилятор знает только о объявленных типах.

Поэтому вывод:

System.out.println("Radius = " + c.r); 

Печатается 100.0 как переменная типа Circle, поэтому компилятор записывает доступ к полевым Circle.r в байт-код.

Смежные вопросы