Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Constructor Create(aColor: Integer);
Procedure Draw; {Заголовок метода} End; Implementation ......... {Описание конструктора} ......... {Описание метода Draw} Procedure UsingFigure; {Описание процедуры, использующей объект класса TGeomFigure} Var Figure: TGeomFigure; begin Figure:= TGeomFigure.Create(3); {Создание экземпляра класса TGeomFigure} Figure.Draw; {Вызов метода Draw} Figure. Color:= 13; {Изменение значения свойства Color} end; End.
5.3.3. Разрушение объекта. Деструктор Объект, естественно, занимает место в памяти, которая необходима для хранения как свойств объекта, так и дополнительной информации, например, таблицы виртуальных методов. Для разрушения объекта и освобождения памяти, которая выделена для него в конструкторе, предназначен деструктор — специализированный метод, изначально определенный в классе TObject: Destructor Destroy; virtual; Если в конструкторе объекта производится выделение памяти под какие-либо ресурсы или объект регистрируется в других объектах, передавая им ссылку на себя, то возникает необходимость переопределения деструктора для освобождения памяти и разрушения связей с другими элементами программы. При переопределении деструктора необходимо указывать ключевое слово override, так как деструктор является виртуальным методом (помечен ключевым словом virtual в описании класса TObject). Последней командой описательной части деструктора должен быть вызов переопределенного деструктора родительского класса с помощью ключевого слова Inherited: Inherited Destroy; Прямой вызов деструктора не применяется для уничтожения экземпляра класса. Для этого предназначен метод Free, также описанный в классе TObject. Данный метод не может быть переопределен, так как не имеет в своем описании ключевого слова virtual, однако метод Free вызывает деструктор Destroy, поведение которого может быть специфическим (листинг 5.15). Листинг 5.15. Пример создания и разрушения объекта unit Geom4; Interface Type TGeomFigure = class {Заголовок класса TGeomFigure, класс автоматически является наследником класса TObject} Protected Color: Integer; {Описание свойства с областью видимости protected} Public Constructor Create(aColor: Integer); {Заголовок конструктора (область видимости public) } Destructor Destroy; override; {Заголовок деструктора (область видимости public) } End; Implementation {Заголовок описательной части конструктора}
Constructor TGeomFigure. Create; Begin Inherited Create; {Вызов конструктора родительского класса} Color:= aColor; {Инициализация свойства, которая не может быть выполнена в родительском классе, так как свойство Color описано в классе TGeomFigure} end; Destructor TGeomFigure.Destroy; {Заголовок описательной части деструктора} Begin Inherited Destroy; {Вызов деструктора родительского класса} end; Procedure UsingFigure; {Описание процедуры, использующей объект класса TGeomFigure} Var Figure: TGeomFigure; Begin Figure:= TGeomFigure.Create(3); {Создание экземпляра класса TGeomFigure}
Figure. Draw; {Вызов метода Draw} Figure. Color:= 13 ; {Изменение значения свойства Color} Figure. Free; {Разрушение объекта, автоматический вызов деструктора Destroy} end; End.
ПОЛИМОРФИЗМ Совместимость объектов
Очевидно, что при наследовании классов друг от друга количество свойств и методов увеличивается от класса к классу (или, как минимум, не уменьшается). Все объекты некоторого класса могут иметь доступ к методам и свойствам, реализованных в тех классах, от которых он унаследован. В результате такого свойства объектов появляется теоретическая возможность присвоить переменной-ссылке на экземпляр класса реальную ссылку на экземпляр другого класса. Причем присваиваемый объект должен быть экземпляром класса, находящимся ниже по иерархии, чем тот, который был указан при описании переменной.
Рис. 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; Interface Procedure DrawFigure (Figure: TGeomFigure); {Заголовок процедуры} Implementation Procedure DrawFigure (Figure: TGeomFigure); {Описание процедуры} Begin If Figure is TLine {Проверка соответствия объекта, на который указывает переменная Figure, классу TLine} Then Figure. Draw {Если тип объекта — TLine, то вызывается метод Draw} Else Expend; {В противном случае — выход из процедуры} End. Оператор as В рассмотренном примере (листинг 5.17) допускается вызов метода Draw из объекта, на который указывает параметр Figure, переданный в процедуру, так как заявленный тип параметра позволяет это сделать — в классе TGeomFigure описан метод Draw. Однако иногда требуется вызвать метод, который реализован не в заявленном классе, а в его наследнике, реальный экземпляр которого и передается в качестве параметра. Попытка сделать это вызовет ошибку компиляции. Для указания компилятору о том, что объект следует рассматривать как экземпляр какого-либо конкретного класса, предусмотрен оператор as, используемый следующим образом: <Ссылка на объект> as <Название класса> В результате такого указания Delphi пытается обращаться к объекту, на который указывает ссылка, как к экземпляру заданного класса. Так. если бы в описании класса TGeomFigure не было метода Draw, а описание его располагалось бы в классе TLine, то метод можно было бы вызвать следующим образом: If Figure is TLine {Проверка соответствия объекта, на который указывает переменная Figure, классу TLine}
|
||||||||||||||||||||||||||||||
Последнее изменение этой страницы: 2021-04-04; просмотров: 45; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.223.134.29 (0.025 с.) |