Почему методы могут быть переопределены, а атрибуты - нет? - PullRequest
14 голосов
/ 27 марта 2019

У меня есть класс

public class A {
    public String attr ="A attribute";
    public void method() {
        System.out.println(this+" , "+this.attr);
    }
    public String toString() {
        return("Object A");
    }
}

и другой класс, который наследует от него

public class B extends A{
    public String attr = "B attribute";
    public void method() {
        super.method();
    }
    public String toString() {
        return("Object B");
    }
}

Обратите внимание, что method() из B - это просто оболочка для method() из A.

Когда я запускаю следующий код

B b = new B();
b.method();

Я получаю Object B , A attribute в качестве вывода, что означает, что this и this.attr обращаются к разным вещам. Почему это так?

Не следует ли System.out.println(this) ссылаться на toString() метод класса A?

1 Ответ

14 голосов
/ 27 марта 2019

Объявляя метод с тем же именем, что и у родительского класса, вы переопределяете , то есть заменяете исходное поведение. Но если вы объявляете поле с тем же именем, вы фактически скрываете его, делая его недоступным для этого подкласса, но только на super.field. См. Документы Oracle для скрытия переменных , а также использование ключевого слова super . Обратите внимание, что не рекомендуется использовать скрытие переменных, поскольку это создает именно ту путаницу, с которой вы столкнулись.

При вызове super.method() печать this приводит к вызову метода toString, который фактически был переопределен - так вот почему он печатает «Объект B», так как вы вызвали метод в экземпляре of B. Но this в this.attr на самом деле относится к родительскому объекту, так как вы вызываете method из родительского класса (super.method()).

...