Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Листинг 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}

Then (Figure as TLine).Draw

{Если тип объекта — TLine, то вызывается метод Draw}

Else Exit; {В противном случае — выход из процедуры}

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

5.4.3. Абстрактные методы

Использование наследования и связанного с ним свойства полиморфизма очень удобно при проектировании сложных систем, состоящих из групп классов, имеющих смысловое единство. Такие классы обычно имеют одного родителя, в котором прописываются заголовки методов, необходимых для поддержки функциональности ветви иерархии. В рассматриваемых нами примерах таким классом был TGeomFigure, в котором метод Draw описывался, но не выполнял каких-либо конкретных действий.

Для того, чтобы не описывать «пустых» методов, увеличивая бесполезный размер исходного текста программ, в Delphi предусмотрен специальный модификатор методов abstract (англ. Abstract — абстрактный, фиктивный):

Procedure <Класс>.<Метод>(<Список параметров>); virtual; abstract;

Или для методов-функций:

Function <Класс>.<Метод>(<Список параметров>): <Тип значе-ния>; virtual; abstract;

Описание метода, помеченного ключевым словом abstract, в классе, где он описан, не требуется, однако и вызвать его из экземпляра данного класса невозможно. При попытке произвести такой вызов возникнет ошибка времени выполнения программы"Project Projectl.exe raised exception class EAbstractError with message 'Abstract Error'."— "Исключительная ситуация EAbstractError в проекте Projectl.exe".

Абстрактный метод всегда является виртуальным (помечен ключевым словом virtual) или динамическим (помечен ключевым словом dynamic) и может быть переопределен в одном из классов-потомков. Соответственно, из экземпляров классов, переопределивших абстрактный метод, его вызов возможен.

Абстрактные методы называют иногда чисто виртуальными, пример их использования приведен в листинге 5.18.

Листинг 5.18. Использование абстрактных методов;

unit AbstractMethods;

Interface

Type

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

Procedure Draw; virtual; abstract;

End; {Заголовок абстрактного метода. Описательная часть класса не содержит реализации данного метода}

TLine = class Procedure Draw; override;

End; {Описание класса Tline с переопределенным методом Draw}

Implementation

Procedure TLine.Draw;

Begin

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

end; {Описание метода Draw класса TLine, -который в классе-родителе описан как абстрактный}

Procedure OsingPolymorph;

Var GeomFigure: TGeomFigure; {Переменная — ссылка на экземпляр класса TGeomFigure}

Begin

GeomFigure:= TLine.Create;

GeomFigure.Draw; {В момент выполнения такого вызова переменная GeomFigure должна указывать не на экземпляр класса TGeomFigure, а на экземпляр класса-наследника, переопределившего абстрактный метод Draw. В данном случае, это экземпляр класса TLine}

GeomFigure.Free;

end;

End.

 

5.4.4. Полиморфизм и property-свойства

Рассмотрим пример, приведенный в листинге 5.19. Отметим использование свойства полиморфности объектов в рассмотренном примере. При установке значения property-свойству Color автоматически вызывается метод SetColor, которому в качестве параметра передается новое значение цвета. Данное значение заносится в protected-свойство f Color, а затем производится автоматический вызов метода Draw.

Метод Draw является виртуальным и может быть переопределен в классах-наследниках. При установке какого-либо значения property-свойству Color класса-наследника будет вызвана та версия метода Draw, которая описана именно в нем, а не в классе TGeomFigure. Таким образом, при отсутствии информации о виде фигур, выводимых классами-наследниками, в классе TGeomFigure полностью реализована логика изменения цвета этой фигуры.

Такой подход позволяет локализовать отдельные фрагменты логики сложных классов уже на стадии проектирования вершины иерархии, существен­но упрощая тем самым разработку программного продукта в целом.

Листинг 5.19. Полиморфизм и property-свойства

unit Geom5;

Interface

Type

TGeomFigure = class

Protected

fColor: Integer; {Описание свойства с областью видимости protected}

Procedure Draw; virtual, {Метод прорисовки геометрической фигуры (виртуальный, предназначен для переопределения в классах-наследниках)}

Procedure SetColor(aColor: Integer);

{Процедура установки protected- -свойства fColor}

Public

Property Color: Integer read fColor write SetColor;

{Описание property-свойства Color}

End;

Implementation

Procedure TGeomFigure.SetColor(aColor: Integer);

Begin

fColor:= aColor; Draw;

end; {Процедура установки protected-свойства fColor заносит новое значение свойства в protected-свойство fColor и вызывает метод Draw для автоматической перерисовки фигуры при смене ее цвета}

Procedure TGeomFigure.Draw;

Begin

end;

Procedure UsingFigure;

Var

Figure: TGeomFigure;

iColor: Integer;

Begin

Figure:= TGeomFigure.Create(3);

Figure.Color:= 13; {Изменение значения property-свойства Color, автоматически вызывается метод SetColor, изменяющий значение свойства fColor, и метод Draw, выводящий изображение фигуры на экран с использованием нового цвета}

iColor:= Figure.Color; {Обращение к property-свойству Color. В качестве значения, В соответствии с описанием данного property-свойства, возвращается значение свойства fColor}

Figure.Free,

end;

End.

5.5. Ключевое слово Self

Для выполнения некоторых задач, методам, реализованным в классе, иногда требуется сослаться на объект (экземпляр класса), из которого вызван метод во время выполнения программы. Поскольку такая ссылка на экземпляр не всегда известна в процессе разработки программы, в Delphi введено ключевое слово Self, вместо которого на этапе выполнения будет подставлен конкретный адрес объекта. Ссылка Self может использоваться как обычная переменная, ссылающаяся на класс.

В качестве примера можно привести метод некоторого класса, который выдает ссылку на экземпляр, из которого вызван данный метод во время выполнения программы:

Туре

AnyClass = class

Function GetSelf:TObject;

end;

Function AnyClass.GetSelf: TObject;

Begin

Result:= Self; {Возвращаем ссылку на экземпляр,

из которого вызван метод}

end;

End.

Использование ссылки Self может быть необходимо при создании компонентов, в конструкторе которых следует передать ссылку на компонент-владелец, не известную на этапе разработки программы.

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...