try {создание формы}

application. CreateForm(tForm1,Form1);

application. Run;

except

on E:Exception do

begin messageBox(E. message,’Y’,mb_Ok);

E. message:='Ошибка в программе';

Raise;

end{/do};

end{/except};

Замечание: исключения, в отличие от других типов, принято именовать с буквы "E", а не с "t".

Некоторые важнейшие типы исключений:

EMathError — все математические ошибки; EInOutError — все ошибки ввода-вывода; EConvertError — ошибки преобразования типов; EOutOfMemory — нехватка памяти; EPrinter — ошибка работы с принтером; EAbort — вызывается программно вызовом процедуры Abort; не делает ничего и предназначена для обработки программистом для нужд текущей программы.

Блоки защиты ресурсов и обработчики исключительных ситуаций могут быть вложенными. Например, выделение ресурсов можно производить так:

try {1}

allocateResource1;

try {2}

allocateResource2;

UseResources;

finally{2}

FreeResource2;

end{/try2};

finally{1}

FreeResource1;

end{/try1};

Другой вариант решения этой проблемы:

const Ok1,Ok2:Boolean:=False;

...

try

AllocateResource1;

Ok1:=True;

AllocateResource2;

Ok2:=True;

except

on Exception do

begin

if Ok2 then

begin

FreeResource2;

if Ok1 then FreeResource1;

end{/if};

end{/do};

end{/except};

Можно вкладывать друг в друга обработчики исключений:

procedure ECheck(var A, B,Y, Z:Real);

var X:Real;

begin

try{1}

X:=(-B*X+sqrt(B*B-4*A*C))/(2*A);

try{2}

Z:=X/sqrt(A*Y*Y-7*B/A/(X-3sqrt(B)));

НЕ нашли? Не то? Что вы ищете?

except{2}

on EMathError do

application. MessageBox('ошибка в вычислении Z',Y, mb_Ok);

end{/except2};

except{1}

on EMathError do

application. MessageBox('ошибка в вычислении корня

уравнения ',Y, mb_Ok);

end{/except1};

end{/ECheck};

Для создания собственной исключительной ситуации в случае, когда обычные исключения не возбуждаются, надо описать соответствующий класс, например:

EWrongPassword=

class(Exception)

end;

В теле класса можно ничего не описывать! В реализации программы в нужный момент надо инициализировать исключение с помощью конструктора, и тогда обработчик исключений сможет его обработать.

Например:

var S, S1:String;

try

S:=...

...

myReadPassword(S1);

if(S1<>S)then EWrongPassword. Create('Wrong password!');

...

except

on EWrongPassword do...;

end{/except};

...

Создание и обработка исключительных ситуаций позволяют структурным способом решить проблемы, в которых в обычном PASCAL приходилось использовать метки и оператор goto, а также ставить огромное число проверок на допустимость присваиваний и математических операций. Мало того, что эти проверки резко замедляли работу программы — не было гарантии, что они достаточны, и что во время работы программы не возникнет "вылет" из-за возникновения непредусмотренной исключительной ситуации. В Object Pascal, как мы видим, эта проблема решена кардинально.

Замечание: в "С-образных" языках С++, JavaScript и Java также имеется обработка исключительных ситуаций, построенная по варианту try...catch..., аналогичная try...except... для Object Pascal (слово "catch" означает "перехватить"). Существенное отличие — после обработки одного исключения производится переход к следующему, если не поставить оператор break, такая логика работы очень часто приводит к ошибке, которую можно назвать "забытый break ".

4.14. Специальные средства для работы с MS Windows: сообщения.

Для обработки сообщений Windows в Delphi существует механизм динамических методов, называемых сообщениями. Они должны быть описаны в классе как процедуры, имеющие один параметр, передаваемый по имени (через var). После описания заголовка через ";" должно идти зарезервированное слово message, после которого идет индекс — идентификатор сообщения. Описание параметра, передаваемого в процедуру через var, произвольно (в первоначальной версии Delphi параметр должен был описываться как переменная соответствующего для message типа : tWM_Size, tWM_Move, и т. д.):

type

tMyControl1=

class(tWinControl)

procedure WMSize(var message:tWMSize);message WM_Size;

{начальный вариант синтаксиса}

end;

tMyControl2=

class(tMyControl1)

procedure Resize(var Info);message WM_Size; {так тоже можно}

end;

В модуле Messages описаны обработчики практически всех необходимых сообщений Windows. Каждый обработчик имеет идентификатор — целочисленную константу. Например, WM_Size — идентификатор сообщения об изменении размера экранной формы, WM_Move — идентификатор сообщения о ее перемещении и т. д.

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

Самый общий обработчик — метод DefaultHandler, описанный в классе tObject. При обработке сообщения обычно надо вызвать в конце обработчик для прародителя:

procedure MyMsgHandler(var message);message WM_command;

begin

MyProcessing; {некая процедура обработки сообщения}

inherited; {в отличии от конструктора, вызов в самом конце}

end;

При получении объектом от операционной системы Windows сообщения описанного типа (идентификация сообщений происходит автоматически по индексам) вызывается соответствующий обработчик. В описанном выше примере это MyMsgHandler.

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

При необходимости обработки сообщений в обработчике события (см. следующий параграф) надо вызвать метод application. processMessages.

4.15. События и их делегирование. Обработка событий.

События — это свойства процедурного типа. Их название принято начинать с префикса "on". Для описания события некого типа (как описать новый тип события будет рассказано далее) в объекте надо описать поле того же типа, что и свойство. Реально это поле служит указателем на процедуру обработчика события. Кроме того, надо описать собственно свойство:

fOnMyEvent:tMyEvent;

property OnMyEvent:tMyEvent

read fOnMyEvent

write fOnMyEvent;

Тут поле fOnMyEvent является ссылкой на процедуру, с помощью которой осуществляется обработка события. Это поле доступно по чтению и записи! Присваивание свойству значения — это присваивание полю fOnMyEvent указателя на метод, который будет вызываться при наступлении события. Чтение — это метод. Эти методы называются обработчиками событий. Если никакой обработчик не присвоен полю-указателю, то там хранится значение notAssigned.

Пример:

присваивание

application. onActivate:=MyMethod; {MyMethod — имя некой процедуры – обработчика события}

означает, что при запуске приложения будет сначала выполнена процедура MyMethod.

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

Общим для описания типа "событие" является первый параметр Sender типа tObject и ключевая фраза of object после описания типа. Ниже приведен пример задания и использования определенного пользователем типа события tMyEvent:

type

{tNotifyEvent=procedure(Sender:tObject)of object;}

{предопределенное простейшее событие}

tMyEvent=procedure(Sender:tObject;var aMyVar:tMyVar) of object;

tObj1=

class

fOnMyEvent:tMyEvent;

property onMyEvent:tMyEvent

read fOnMyEvent

write fOnMyEvent;

end;

tObj2=

class

procedure MyEventProcessing1(Sender:tObject;

var aMyVar:tMyVar);

procedure MyEventProcessing2(Sender:tObject;

var aMyVar:tMyVar);

end;

...

var aObj1:tObj1;

aObj2:tObj2;

myKey:Boolean;

begin

aObj1:=tObj1.Create;

aObj2:=tObj2.Create;

...

if MyKey

then

aObj1.onMyEvent:=aObj2.MyEventProcessing1

else

aObj1.onMyEvent:=aObj2.MyEventProcessing2;

...

end.

При делегировании можно присваивать методы других классов! Даже не являющихся потомком и прародителем! Но при этом должно быть полное соответствие списков параметров обработчиков событий со списком параметров процедурного типа события.

4.16. Методы класса и указатели на класс.

Некоторые методы бывает нужно вызывать без создания экземпляра класса (например, для получения информации о имени класса, размере экземпляра класса и т. п.). Такие методы называются методами класса - в C++ и Java они называются статистическими методами (не путать со статистическими методами в смысле TP и Delphi!). Методы класса имеют перед словами procedure или function ключевое слово class (за исключением конструкторов, которые также являются методами класса, но для которых синтаксис, как мы знаем, другой):

type

tMyObj=

class

class function MyGetSize:String;

end;

var aMyObj:tMyObj;

begin

...

Label1.caption:=tMyObj. MyGetSize; {вызов метода класса tMyObj}

aMyObj:=tMyObj. Create; {вызов другого метода класса tMyObj}

Label2.caption:=aMyObj. MyGetSize; {вызов метода класса с

экземпляром класса}

...

end;

Возможно описание указателя на класс с помощью ключевой фразы class of. Это иногда требуется в программах, использующих сложную иерархию объектов, для унифицированного динамического создания, копирования и уничтожения объектов, принадлежащих разным классам. В модуле SysUtils указатель на tObject описан так:

type tObject=class;

tClass=class of tObject;

Имеются следующие важнейшие стандартные функции классов, определенные в tObject:

class function ClassName:string — возвращает имя класса, вызвавшего объект; class function ClassParent:tClass — возвращает указатель на класс прародителя; function ClassType:tClass — возвращает указатель на класс вызвавшего объекта; class function ClassInfo:Pointer — возвращает указатель на структуру (запись), содержащую информацию о классе.

Также имеется ряд других стандартных функций классов.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16