Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие Java .pdf
Скачиваний:
118
Добавлен:
16.03.2015
Размер:
1.32 Mб
Скачать

и приказывает компилятору выбирать одну из двух реализаций метода nm(), принимая во внимание фактический класс объекта. Ниже приведён результат работы метода printNM().

this.nm() = More sref.nm() = More super.nm() = That

Таким образом, ключевое слово super может использоваться одним из трёх способов:

в первой строке конструкторов для вызова конкретного конструктора родительского класса (в форме super(аргументы));

в выражениях для обращения к полю из родительского класса

(в форме super.имяПоля);

в выражениях для вызова метода из родительского класса

(в форме super.имяМетода(аргументы)).

Слово super является единственным способом вызова переопределённого метода. «Извне» объекта (не в его методах) вызвать версию метода, который был переопределён, вообще нельзя.

4.9 Совместимость и преобразование типов

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

4.9.1Совместимость

Влюбой ситуации, когда значение выражения присваивается некоторой переменной, тип выражения должен быть совместим (compatible) с типом переменной. Если говорить о ссылочных типах, это означает, что выражение должно относиться к тому же типу, что и переменная, либо к соответствующему производному типу. Напри-

146

мер, любой метод, для которого предусмотрена передача аргумента типа Attr, способен воспринимать и аргумент типа ColorAttr, если ColorAttr является производным классом базового класса

Attr. Это принято называть совместимостью присваивания

(assignment compatibility). Но обратное утверждение не верно: не удастся ни явно присвоить значение типа Attr переменной класса ColorAttr, ни передать аргумент типа Attr методу, в котором объявлен параметр класса ColorAttr.

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

Значение null – это специальный случай: null позволено присваивать переменным всех ссылочных типов, включая и массивы.

О типах, находящихся на более высоких ступеньках иерархии классов, говорят как о более широких, или менее конкретных, по сравнению с теми, которые расположены ниже. Соответственно, производные типы называют более узкими, или более конкретными, нежели их «прародители». Когда в выражении, предусматривающем использование объекта базового класса, применяется объект производного класса, имеет место преобразование с расширением типа. Подобная операция, допустимость которой проверяется на этапе компиляции, приводит к тому, что объект производного типа интерпретируется программой как объект базового класса. Программисту в этом случае не нужно предпринимать никаких дополнительных усилий. Обратное действие, когда ссылка на объект базового класса преобразуется в ссылку на объект производного класса, называют

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

147

4.9.2 Явное преобразование типов

Оператор преобразования типов позволяет сообщить компилятору, что конкретное выражение следует трактовать таким образом, будто оно относится к тому типу, который явно указан. Оператор может быть применён в любых ситуациях, но его обычное употребление связано всё-таки с преобразованиями, предусматривающими сужение типа. Оператор преобразования типов представляет собой конструкцию, состоящую из наименования требуемого типа, заключённого в круглые скобки, которую размещают непосредственно перед выражением, подлежащим преобразованию. В примере64, а именно в теле метода printMN(), мы уже использовали выражение преобразования с расширением типа:

That sref = (That) this;

Хотя эта попытка преобразования оказалась бесполезной и безуспешной, мы, тем не менее, точно обозначили свои намерения – необходимость интерпретации текущего объекта в виде экземпляра базового класса. Если бы затем мы захотели присвоить sref обратно некоторой ссылочной переменной mref более узкого типа More, наличие операторапреобразованиятиповоказалось бысущественным:

More mref = (More) sref;

Даже в том случае, если подлинный тип объекта, «скрывающегося» за ссылкой, нам известен, его всё ещё следует сообщить компилятору, обратившиськоператору преобразования типов.

Преобразование с расширением типа нередко обозначают терминами преобразование вверх (upcasting) или безопасное пре-

образование, поскольку тип, расположенный на низкой ступени иерархии, приводится к классу более высокого уровня, а подобная операция заведомо допустима. Преобразование с сужением типа соответственно называют преобразованием вниз (downcasting) – воздействию подвергается объект базового типа, который должен быть интерпретирован как объект производного типа. Преобразо-

148

Соседние файлы в предмете Программирование на Java