Создание собственного исключения

Все классы исключений в Delphi являются наследниками классаException.Это означает, что все исключения содержат свойства и методы класса Exception, но могут также содержать дополнительную информацию, специфичную для конкретного исключения. Если никакой дополнительной информации не требуется, то объявление нового класса исключений производится в разделеtype оператором вида: type

«имя_класса_исключения» = class (Exception);

Например, для сообщения об отсутствии какой-то информации можно создать свой класс исключений с именемENoInf. type ENoInf = class (Exception);

В различных местах программы перед выполнением каких-то действий с данными, заданными пользователем, можно проверять полноту информации и при необходимости генерировать исключение оператором вида: raise ENoInf.Create('Be задана требуемая информация');

Текст сообщения формируется при генерации исключения. Это исключение будет перехватываться системными средствами, и пользователю будет выводиться диалоговое окно сообщения об ошибке. Если же требуется конкретизация сообщения пользователю, то можно использовать блоки try ...except, в которых генерировать соответствующие исключения и вставлять в разделexcept их обработку, например: on ENoInf do

MessageDlg ('Укажите цену товара', mtWarning, [mbOk], О);

Пример. Пользователь должен указать в окнах редактированияEditstr и EditNum серию и номер паспорта. Проверка полноты введенной информации: var з: string [8.] ;

if EditSer.Text = '' then s:= 'серию'; if EditNum.Text = '' then if s = 11 then s:= 'номер'; else s:= s + 'и номер' ; if s<»'1 then

raise ENoInf.CreateRnt ('Укажите %s паспорта', [»]);

Если необходимо создать класс исключений, содержащих дополнительные поля, определение такого класса должно иметь вид. type

«имя класса исключения» = class (Exception) «поля» and;

Например, объявление: ЕМу - class (Exception) i

Enum: integer; end;

создает класс исключения с именемЕМу, имеющим открытое поле сименемEnum, в которое вы можете при генерации заносить, например, условный идентификатор, конкретизирующий причину исключения. Использовать такой класс можно следующим образом: type

EMy ш class (Exception) public

Enum : integer; end; var Јxc: EMy;

Try

if -(условие наличии ошибки> then begin

Exe :ш EMy.Create (<текст сообщения»); Exc.Enum Идентификатор вида отивки>; raise Exc; end;

Except on EMy do

Сазе Exc.Enum of

end;

end; ■ ,уШЛ

При ошибке создается экземпляр исключения Ехе и в его поле Епиш заносится условный идентификатор вида ошибки. Затем это исключение возбуждается предложением raise. При обработке ошибки можно предпринять различные действия в зависимости от значения поля Enum.

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

Класс TList

Класс ТЫ at позволяет создать'набор из произвольного количества элементов и организовать индексный способ доступа к ним, как это делается при работе с массивом. TList реализует список значений, но с некоторыми оговорками, которые становятся очевидными при рассмотрении реализации класса.

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

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

Класс TList происходит непосредственно от TObject.

TList = class(TObject)

end;

Технически класс TList реализуется в виде динамического массива безтиповых указателей PPointerLisfc, каждый из элементов массива указывает на область памяти, где расположен элемент списка, const

MaxListSire = Maxint div 16; type

TPcinterList = array[0..MaxListSize-l] of Pointer;

PPointerList ~ "TPointerList;

Количество элементов динамического массива определяется свойством Capacity, количество реальных элементов в списке равно Count. Если при добавлении очередного элемента в список TList Count становится равным Capacity, автоматически происходит расширение динамического массива (для Count < 5 на 4 элемента, для 4 < Count < 8 - на 8 элементов, для Count > 7 - на 16 элементов). При этом сначала резервируется место для размещения расширенного массива указателей, потом происходит копирование текущего массива, затем его удаление. Поэтому, чтобы снизить накладные расходы, в случае если заранее известно приблизительное количество элементов, следует инициализировать свойство Capacity соответствующим значением. Основные свойства класса TList приведены в табл. 5.4.

Таблица 5.4

Свойство Описание
property Capacity: Integer read ^Capacity writ® SetCapacity; Содержит количество элементов массива указателей списка. Всегда больше Count.
property Count: Integer read FCowat write SetCount; Количество элементов списка- изменяется при добавлении и удалении элементов.
property Items [Index: Integer): Pointer read Get write Put; default; Возвращает указатель на элемент списка по его индексу. Индекс первого элемента 0
property List: PPointerList read FList; Возвращает указатель на массив элементов списка,

Основные методы класса TList приведены в табл. 5.5.

__________________ Таблица 5.5

Метод Описание
function Add(Item: Pointer): Integer; Добавляет элемент Item в конец списка и возвращает его индекс
procedure Clear; virtual; Очищает список, не очищает память, связанную с каждым элементом. Устанавливает Count и Capacity В 0.

procedure Delete(Index: Integer); Удаляет из списка элемент с индексомIndex.Все элементы, расположенные за удаляемым смещаются на одну позицию вверх.
class procedure Error(const Msg: string; Data: Integer); overload; virtual; Возбуждает исключениеELiatError с параметрамиMsg иData.
procedure Exchange(Indexl, Index2: Integer); Меняет местами элементы с индексамиIndexlиIndex2
function Expand: TList; Расширяет массив элементов, увеличивая свойствоCapacity.
function Extract(Item: Pointer): Pointer; Удаляет из списка элементItem. Все элементы, расположенные за удаляемым, смещаются на одну позицию вверх. Возвращает указатель удаленного элемента.
function First: Pointer; Возвращает указатель на первый элемент списка
procedure Insert(Index: Integer; Item: Pointer); Вставляет в список элементItem на позицию с индексомIndex.
function Last: Pointer; Возвращает указатель на последний элемент
procedure Move(CurIndex, Newlndex: Integer); Перемещает элемент в списке с позиции Curlndex на позициюNewlndex. Все соответствующие элементы старого списка меняют индексы.
function Remove(Item: Pointer): Integer; Отыскивает в списке элементItem и удаляет его.
procedure Pack; Упаковывает список - удаляет пустые элементывконце массива индексов.
procedure Sort(Compare: TListSortCompare); Сортирует коллекцию с помощью функции Compare.

Для того чтобы воспользоваться методамиAdd, Insert необходимо разместить в оперативной памяти динамические переменные, а в указанные методы передавать полученные указатели. Соответственно методыDelete, Extract, Remove иClear не освобождают динамическую намять, а только очищают ссылки на эти данные. Поэтому, необходимо очищать динамическую память программно. Например: var

List: TList; Item: "Integer; begin

List :=> TList.Create; // создаем список

Наши рекомендации