Создание собственного исключения
Все классы исключений в 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; // создаем список