Смекни!
smekni.com

Методические указания к курсу программирования для студентов физического факультета Сравнительное объектно-ориентированное проектирование (стр. 2 из 8)

TEllipseSprite=class(TTracedSprite)

private

// Поле

// Хранит цвет эллипса

FColor:Graphics.TColor;

protected

// Методы

// Изображает эллипс

procedure PaintPicture;override;

// Устанавливает цвет эллипса

procedure SetColor(const aColor:Graphics.TColor);

public

// Свойство

// Возвращает и устанавливает цвет эллипса

property Color:Graphics.TColor read FColor write SetColor;

// Метод

// Выполняет инициализирующие действия сразу после создания спрайта

procedure AfterConstruction;override;

end;

Вспомним правила описания в Delphi в контексте приведенного выше интерфейса модуля uSprite. С этой целью рассмотрим фрагмент начала модуля

uses Controls,Graphics,Classes,Types;

type

// Предварительное объявление класса TSprite

TSprite=class;

// Тип переменных, содержащих ссылки на классы типа TSprite

TSpriteClass=class of TSprite;

// Список спрайтов

TSpriteList=class

// Описание членов класса

end;

· Директива uses означает, что в коде настоящего модуля используются типы, переменные, процедуры, функции или константы (короче – имена), описанные в интерфейсах модулей Controls, Graphics, Classes, Types. Все перечисленные модули принадлежат в данном случае библиотеке среды Delphi.

· Служебное слово type означает, что ниже следует описание типов. Тип – это формат переменных. Существуют стандартные типы такие как , , и другие. Их формат задан средой. Другие типы, которые оказываются необходимыми в конкретном приложении или модуле, требуют специального описания.

· Краткое описание TSprite=class; типа TSprite означает, что класс TSprite будет описан ниже, но упоминание о нем необходимо уже здесь. Дело в том, что описанный ниже класс TSpriteList использует в своем описании TSprite. В то же время полное описание класса TSprite в свою очередь содержит ссылку на класс TSpriteList. Эта взаимозависимость описаний двух классов не позволяет предпочесть в порядке описания один класс другому. Выход – дать краткое (пустое) описание одного из классов перед полным описанием другого.

· Тип TSpriteClass=class of TSprite описывает переменные, которые содержат в себе ссылки на таблицы виртуальных методов класса TSprite и его наследников. Такие переменные могут быть использованы, например, при создании экземпляра объекта, о котором во время программирования известно лишь то, что он принадлежит к семейству спрайтов, то есть является наследником класса TSprite. Так одним из параметров метода AddSprite(const aSpriteClass: TSpriteClass; const SpriteRect: Types.TRect) класса TSpriteList является переменная типа TSpriteClass, указывающая, экземпляр какого класса спрайтов следует добавить в список.

Строка TSpriteList=class открывает описание класса, которое содержит в себе поля, свойства и методы класса TSpriteList вплоть до служебного слова end, завершающего перечисление членов класса. Все поля объекта инициализируются при явном вызове конструктора в коде приложения. По умолчанию, если в теле конструктора не указаны другие значения, все поля будут инициализированы нулями.

Каждый член класса TSpriteList имеет определенный уровень доступа. Так в описании класса TSpriteList имеется две секции, выделенные модификаторами доступа private и public.

Рассмотрим фрагмент кода, описывающий класс TSpriteList:

TSpriteList=class

private

// Поля

// Хранит канву ("контекст устройства"),используемую для отображения спрайтов списка

FCanvas:Controls.TControlCanvas;

// Метод

// Возвращает спрайт списка под номером aZ

function GetSprite(aZ:integer):TSprite;

public

// Свойства

// Возвращает ссылку на канву, с которой связаны спрайты списка

property Canvas:Controls.TControlCanvas read FCanvas;

// Возвращает спрайт из списка как элемент массива

property Sprites[aZ:integer]:TSprite read GetSprite;default;

// Конструктор

// Создает и инициализирует экземпляр списка спрайтов, связанного с данной канвой

constructor Create(const aCanvas:Controls.TControlCanvas);

end;

В Delphi модификатор доступа private применяется к членам класса, которые доступны лишь тому же модулю, в котором описан сам класс, но недоступны другим модулям программы. Обычно поля класса имеют уровень доступа private. Члены класса с уровнем доступа public доступны любой части программы. Свойства класса обычно имеют уровень доступа public. Так поле FCanvas (идентификаторы полей в Delphi принято начинать буквой F от field – поле) имеет уровень доступа private, но свойство Canvas открыто для доступа. Через свойство Canvas можно прочесть поле FCanvas, но нельзя изменить его значение. Так свойства могут регулировать доступ к полям.

Что касается методов, то их разделение по уровням доступа зависит от логики класса. Так, метод GetSprite(aZ:integer):TSprite класса TSpriteList «спрятан» от внешнего доступа под модификатором private. Его роль ограничивается обеспечением доступного свойства Sprites[aZ:integer] возвращаемым значением – спрайтом с индексом aZ из списка. Другие методы класса TSpriteList имеют открытый доступ. Среди них конструктор класса Create, создающий экземпляр объекта и инициализирующий его поля. Параметром конструктора является объект типа TControlCanvas из библиотечного модуля Controls. Объекты этого типа предоставляют спрайтам область изображения - прямоугольник с известными границами в окне приложения и инструменты изображения – кисть и карандаш с цветовой палитрой.

Модификатор const, указанный в описании параметра конструктора и многих других методов, не является обязательным. Он указывает лишь на то, что метод обязуется внутри не изменять значения параметра, передаваемого ему с этим модификатором.

Модификатор default в свойстве Sprites указывает на то, что доступ к объектам класса TSpriteList может осуществляться через свойство Sprites как к элементам массива – в индексном виде.

В коде настоящего модуля имена, описанные в других модулях, специально записаны в расширенном формате с тем, чтобы явно указать их принадлежность. Например, имя типа TControlCanvas, описанного в модуле Controls, записано в расширенном виде Controls.TControlCanvas. Вообще говоря, расширенное имя можно сократить, убрав имя модуля, если отсутствует конфликт имен.

Метод

procedure BeforeDestruction; override;

имеет модификатор override. Это означает, что метод BeforeDestruction является виртуальным и унаследован от предка класса TSpriteList, где он описан как виртуальный (virtual). Предком класса TSpriteList является класс TObject.

Другие методы

procedure DeleteSprite(const aZ:integer); virtual;

procedure Clear; virtual;

описаны как виртуальные в самом классе TSpriteList. У наследника TTracedSpriteList, эти же методы преобретают модификатор override.

Рассмотрим еще один фрагмент кода, относящийся к описанию Tsprite и следующий за описанием класса TSpriteList.

// Тип обработчика события, наступающего перед смещением спрайта

OnMoveEvent=function(Sender:TSprite;var NewLocation:Types.TPoint):Boolean of object;

// Абстрактный класс спрайта, регулирующий изображение и перемещение спрайта

TSprite=class(TObject)

private

// Конструктор

// Создает и инициализирует спрайт, принадлежащий списку Sprites

// с прямоугольником SpriteRect

constructor Create(const SpriteRect:Types.TRect;const Sprites:TSpriteList);

protected

// Формирует реальное изображение спрайта (в этом классе метод абстрактный)

procedure PaintPicture;virtual;abstract;

public

end;

Здесь

· Тип функции OnMoveEvent, описанный с модификатором of object, означает, что это тип метода класса, а не просто тип какой-то отдельной функции. Разница в том, что метод класса обязательно имеет один скрытый параметр Self - экземпляр класса, который его вызывает. У обычных процедур и функций такого параметра нет. Обработчики событий в Delphi обычно имеют тип метода. Тогда в них можно подставить ссылку на метод либо формы приложения, либо другого класса, использующего объявленное событие в своих целях.

· В заголовке описания класса TSprite в скобках указан предок TObject, хотя такое указание отсутствует в описании класса TSpriteList. В Delphi отсутствие предка по умолчанию означает, что предком является класс TObject. Так что в описании класса TSprite ссылку на TObject можно также опустить.

· Конструктор класса TSprite помещен в раздел private. Это делает невозможным создание экземпляров отдельных спрайтов из кода, написанного вне модуля uSprite. Логика классов TSprite и TSpriteList предполагает, что созданием спрайтов занимается только метод Add класса TSpriteList, который только и вызывает конструктор экземпляров класса TSprite.

· В описании класса TSprite присутствуют методы с уровнем доступа protected. Эти методы и вообще члены класса с доступом protected доступны любому предку класса TSprite, даже если они описаны в других модулях, но не доступны коду других классов, описанных в других модулях.

· Среди методов класса TSprite, защищенных модификатором protected есть абстрактный метод procedure PaintPicture; virtual; abstract. Он отмечен модификатором abstract. Абстрактный метод PaintPicture не имеет реализации в классе TSprite. Его реализация будет предложена наследниками. Наличие абстрактного метода делает сам класс TSprite абстрактным в том смысле, что его экземпляры не могут быть созданы.

После описания класса TSprite описаны один тип динамического массива

// Тип массива, хранящего карту следов (пикселей) спрайтов на канве

TTraceMap=Array of array of Boolean;

Тип TTraceMap описывает двумерный массив логических значений.

Динамичность массива в том, что его размер не фиксируется как постоянная величина в процессе разработки класса (design time), а определяется лишь в ходе счета (run time). Конкретные переменные, например, размеры области изображения спрайтов, приобретают реальные значения при создании экземпляра класса TTracedSpriteList=class(TSpriteList). Это происходит в методе AfterConstruction класса TTracedSpriteList, выполняющемся сразу вслед за созданием экземпляра объекта этого класса.

За описанием класса TTracedSpriteList и перед описанием класса TtracedSprite есть описание другого типа динамического массива

// Тип массива точек следа спрайта

TTracePoints=array of Types.TPoint;

Это уже одномерный массив точек - записей типа TPoint, описанных в стандартном модуле Types.

Вслед за этим описан класс

TTracedSprite=class(TSprite)

наследник класса TSprite.

Обратите внимание, что класс TTracedSprite, как и его предок TSprite, является абстрактным классом, так как не реализует абстрактный метод PaintPicture.

Вслед за описанием класса TTracedSprite расположен текст

const DefaultColor=$ffffff; //Цвет эллипса по умолчанию