Поля наследования Java
Я не могу понять следующий вывод.
Я не знаю, почему вывод равен 10, я думаю, что строка A a = new B()
создает новый экземпляр класса B, я думаю, что результат должен быть 20
class A {
int i = 10;
}
class B extends A {
int i = 20;
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i);
}
}
Почему это работает так, пожалуйста, объясните.
Ответы
Ответ 1
Во-первых, см. Скрытие полей (выделено мной)
Внутри класса поле, имеющее то же имя, что и поле в суперклассе , скрывает поле суперкласса, даже если их типы отличаются друг от друга
Другими словами, это не "наследование", поскольку вы на самом деле скрываете A
i
за B
i
, и вы используете ссылочный объект A
, поэтому вы получаете его полей. Если вы сделали B b = new B()
, вы увидите 20
, как и ожидалось.
Если вы ожидаете истинных переопределений, попробуйте использовать методы.
class A {
public int get() {
return 10;
}
}
class B extends A {
@Override
public int get() {
return 20;
}
}
См
A a = new B();
System.out.print(a.get()); // 20
Если вы действительно хотите увидеть оба сразу, см. этот пример.
class A {
int i = 10;
}
class B extends A {
int i = 20;
@Override
public String toString() {
return String.format("super: %d; this: %d", super.i, this.i);
}
}
И
A a = new B();
System.out.print(a); // super: 10; this: 20
Ответ 2
В java вы не можете переопределить переменную экземпляра. Ожидается выход, который вы получаете. В Java вы можете переопределять только методы экземпляра, а не переменные экземпляра.
Если вы хотите использовать 20 в качестве вывода, вы можете использовать методы getter над этими переменными экземпляра.
class A {
int i = 10;
int getI() {
return i;
}
}
class B extends A {
int i = 20;
int getI() {
return i;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.getI());
}
}
Ответ 3
Полиморфизм не применим для полей в Java. Решение об оценке переменных принимается во время компиляции, поэтому всегда доступны переменные базового класса.
Ответ 4
Поскольку вы определяете две переменные: одну в подклассе B
и одну с тем же именем в суперклассе A
.
A a = new B();
a.i; // refers to A.i
Если вы нажмете A
на B
, он получит доступ к B.i
:
System.out.println(((B)a).i);
Я думаю, вам нужно использовать 1 переменную:
class A {
int i;
public A() {
i = 10;
}
}
class B extends A {
public B() {
i = 20;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i); // will print 20
}
Ответ 5
Членная переменная i
уже определена в class A
.
Чтобы добиться того, что вы ищете, измените class B
, как показано ниже:
class B extends A {
public B() {
i = 20;
}
}