Подтвердить что ты не робот

Поля наследования 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);
    }
}

Почему это работает так, пожалуйста, объясните.

4b9b3361

Ответ 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;
    }
}