Наследование в Java - PullRequest
       5

Наследование в Java

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

Я столкнулся с этим примером о наследовании в Интернете, и мне нелегко с его результатами. Я упускаю что-то критическое.

public class A {

int i = 5;

public A() {
    foo();
}

private void foo() {
    System.out.println(i);

}}

public class B extends A {
int i = 6;}

public class C extends B {
int i = 7;

public void foo() {
    System.out.println("C's foo");
    System.out.println(super.i);
}}

Я пытаюсь выяснить, что происходит, с помощью следующей команды: C c = new C(); System.out.println(C.i);

Я знаю, что когда мы создаем новый экземпляр C, мы приближаемся к конструкциям A и B, поэтому мы достигаем A() - (вопрос 1) Инициализируется ли i (из A) в пути? Теперь нам нужно обратиться к foo() - (вопрос 2) - Считает ли C foo() переопределением A 1012 *? а что если у B foo() самого себя? тогда это рассматривалось как переопределение и C foo() был оперирован?

Насколько я знаю, нет переопределения, когда оно относится к локальным переменным. Почему System.out.println(c.i) равно 7, а не 5? не должно ли это быть i от высшего отца?

РЕДАКТИРОВАТЬ: Мой вопрос не о том, какой foo и я буду использовать, когда я использую c, а о том, что происходит во время этих двух конкретных команд, потому что, очевидно, использовался foo A, а не C.

Большое спасибо.

Ответы [ 4 ]

5 голосов
/ 02 сентября 2011

Три i переменные здесь полностью независимы.Какой из них используется любым оператором, определяется в время компиляции - полиморфизм не задействован.Так что A.foo() всегда будет выводить значение переменной, объявленной в A.

Обратите внимание, что это не локальные переменные, кстати - они экземпляр переменных.

При выводе c.i, который использует переменную, объявленную в C, поскольку тип времени компиляции c равен C.Вы можете увидеть это, если напишите:

C c = new C();
A a = c;
B b = c;
System.out.println(a.i); // 5 - variable declared in A
System.out.println(b.i); // 6 - variable declared in B
System.out.println(c.i); // 7 - variable declared in C

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

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

О переопределении метода и видимости:

A.foo () является приватным.Это означает, что это не видно его подклассам.Если вы хотите, чтобы B или C переопределяли A.foo (), A.foo () должен быть защищенным или общедоступным.Так что в вашем коде B.foo () не существует, потому что B не знает об A.foo ().

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

A, B и C каждая имеет переменную экземпляра, называемую «i».Если у вас есть объект C и вы выполняете foo (), вы напечатаете значение C для «i».

Если вы поместили foo () в B, а не в C, как ни странно, вы все равно получите значение C для «»i "если у вас есть объект C, так как будет использоваться" самая внешняя "версия" i ".

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

Нет, вы всегда используете члена класса, ближайшего к классу, который вы создали. Итак, C c = новый C (); будет использовать i = 7 и только c foo. Класс B i переопределяется классом C i, так же, как A i переопределяется B i. Там нет цепочки, просто переопределение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...