Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основные механизмы и положения объектно-ориенти...doc
Скачиваний:
3
Добавлен:
01.05.2025
Размер:
261.12 Кб
Скачать

5.4. Полиморфизм

5.4.1. Совместимость объектов

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

Н

Класс А

Экземпляр

а рис. 5.1 представлены классы, образующие иерархию. Один из классов -Класс А — является родительским для всех остальных. Соответственно, если некоторая переменная описана как ссылка на экземпляр Класс А, то на самом деле она может указывать еще и на Класс Б, и на Класс В.

Класс Б

Экземпляр

Класс в Экземпляр

Рис. 5.1. Совместимость объектов

Как и все объектно-ориентированные языки программирования, Delphi поддерживает свойство полиморфизма объектов при наследовании, которое состоит в правильном выборе виртуального метода, вызываемого из переменной-ссылки на объект. Вне зависимости от того, на экземпляр какого класса указывает переменная-ссылка в соответствии со своим описанием, будет вызван виртуальный метод, описанный в классе, на который реально указывает ссылка, а не его версия, описанная в классе, сопоставленном типу ссылочной переменной.

Рассмотрим (листинг 5.16), например, классы Tline HTCircle, являющиеся наследниками класса TGeomFugure и переопределяющие вирту­альный метод Draw, чтобы придать ему функциональность, необходимую для вывода каждой конкретной геометрической фигуры. Опишем пере­менную, которая является ссылкой на экземпляр класса TGeomFigure и присвоим ей ссылку на экземпляр класса TLine.

Такая операция возможна, так как класс TLine является наследником класса TGeomFigure. При вызове метода Draw данной переменной этот метод будет вызван в том виде, как он описан в классе TLine, а не в классе TGeomFigure. В этом и выражается полиморфизм (многоформенность) объектов, находящихся в одной иерархии.

Свойство полиморфизма поддерживается с помощью так называемого по­зднего связывания (происходящего во время выполнения программы) переменных-экземпляров с методами, в отличие от раннего связывания (на этапе компиляции).

Листинг 5.16. Иллюстрация полиморфизма

unit PolymorphObjects;

Interface Type

TGeomFigure = class {Описание класса TgeomFigure с виртуальным методом Draw}

Procedure Draw; virtual;

End;

TLine = class

Procedure Draw; override; {Описание класса TLine с переопределенным

методом Draw}

End;

Implementation

procedure TGeomFigure .Draw;

Begin {Описание метода Draw класса TGeomFigure, метод ничего не делает}

End;

Procedure TLine.Draw;

begin

{Вывод линии}

end; {Описание метода Draw класса TLine,

метод выводит линию}

Procedure UsingPolymorph;

{Описание процедуры, использующей полиморфизм объектов}

Var

GeomFigure: TGeomFigure; {Описание переменной-ссылки на экземпляр класса TGeomFigure}

begin

GeomFigure := TLine.Create; {Создание экземпляра класса TLine и занесение ссылки на него в переменную-ссылку на экземпляр класса TGeomFigure}

GeomFigure.Draw; {Вызов метода Draw из переменной GeomFigure, реально вызываемый метод описан в классе TLine (рисование линии) }

GeomFigure.Free; {Разрушение объекта, на который указывает переменная GeomFigure, если бы класс TLine переопределял деструктор, то был бы вызван деструктор, описанный в классе Tline}

end;

End.

5.4.2. Определение принадлежности к классу и приведение типов объектов

Оператор is

При использовании полиморфизма нередко требуется определить, ссылка на объект какого именно типа находится в той или иной переменной. Для решения задач такого рода все объекты содержат информацию о классе — так "называемую RTTI-информацию (от англ. Run Time Type Information — информация времени выполнения о типе), для доступа к которой во всех классах имеются методы, унаследованные ими от класса тobject. Однако использование этих методов не рекомендуется разработчиками, а вместо них предусмотрен оператор is, проверяющий при­надлежность объекта к заданному классу.

Оператор is возвращает логическое значение (True или False) и используется в следующем виде:

<Ссылка на объект> is <Название класса>

Проиллюстрируем использование оператора is на примере модуля (листинг 5.17), подключающего к себе модуль PolymorphObjects, разработанный в предыдущем примере. Реализуем процедуру, которая получает в качестве параметра ссылку на экземпляр класса TGeomFigure, и определяет, не принадлежит ли объект, на который реально указывает ссылка, к классу TLine. Если объект является экземпляром класса TLine, то вызо­вем его метод Draw, в противном случае процедура должна завершиться.

Листинг 5.17. Использование оператора is

unit CheckClass;

Uses PolymorphObjects;