Как приведение типов работает в java для доступа к родительскому члену?

class Grand {
    int x = 10;
}

class Parent extends Grand{
    int x = 20;
}

class Childs extends Parent{
    int x = 30;
    void show(){
    System.out.println(this.x);
    System.out.println(super.x);  //accessing parent's member
    System.out.println((Grand)this.x);   //why type-casting
}

Я знаю, что с помощью ключевого слова super в Java мы можем получить доступ к родительскому методу / члену, который скрывается / переопределяется дочерним методом / членом.

Но при многоуровневом наследовании мы обращаемся к родительскому методу, используя приведение типов дочернего объекта.

Как происходит внутреннее преобразование типов для доступа к члену родительского класса суперпользователя. Есть ли другой способ сделать это?

Можем ли мы получить доступ к методам аналогичным образом, используя приведение типов?

Методы можно переопределить, но нельзя переопределить поля. Узнайте о виртуальных методах / переопределении.

SLaks 21.08.2018 17:08
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
545
2

Ответы 2

Вам нужно выполнить приведение, потому что поля экземпляра не переопределяются (как это делают методы).

Когда вы повторно объявляете поле родителя в дочернем классе, вы становитесь прячется родительским полем.

А когда поле скрыто, вы используете ссылку родительского типа для чтения значения родительского поля:

Итак, для чтения поля Grand необходимо любое из них:

((Grand)this).x

Или:

Grand grand = this
int val = grand.x //reads parent's x

Надеюсь, это проясняет, что скрытие полей - плохая идея.

Короче говоря, с большим упрощением, объекты в памяти представлены как указатели на область, которая содержит все их элементы поля (уникальная копия области для каждого экземпляра объекта) и таблица / область, которые содержат указатели на функции-члены (по одному на класс, то же самое). для всех объектов).

В Java все члены-функции являются виртуальными, поэтому, переопределяя член-функцию, вы переопределяете ячейку в таблице памяти виртуальных методов. Таким образом, виртуальный в основном означает возможность переопределения. Также есть специальный указатель, называемый «super», который указывает на таблицу виртуальных методов родительского класса. Таким образом, вы можете получить доступ к этой таблице по ключевому слову super.

Если вы объявляете элементы-поля в предках, вы расширяете область экземпляра родительского объекта, т.е. все поля предков в памяти идут после родительских. Но поскольку вы используете одинаковые имена для обоих, это создает двусмысленность, поэтому компилятор предупреждает, что вы «скрываете» члены. Они не переопределяются как функции, они все еще существуют, но компилятор выбирает фактическое поле для доступа как то, которое объявлено в классе, в зависимости от типа указателя, который вы используете. Если вы не укажете какой-либо указатель, this будет неявно рассматриваться как «this», и типом будет предок, то есть поле предка. Чтобы получить доступ к полю родительского класса, вам нужно привести (этот) указатель к родительскому классу, поэтому компилятор выберет поле родительского класса, которое вы скрываете в предке.

Разница здесь в том, что все объекты одного класса используют одни и те же методы, но значения полей не разделяются между экземплярами объекта.

Другие вопросы по теме