Шаг 30.
Средства отладки в Borland Delphi 4.0. Преднамеренная генерация исключений. Оператор Raise

    На этом шаге мы рассмотрим преднамеренную генерацию исключений.

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

  1. При обработке исключения требуется завершить эту обработку во внешнем обработчике по отношению к данному блоку Try...Except. В этом случае Вам надо повторно сгенерировать исключение этого же типа, что и прежнее, так как прежнее разрушено данным обработчиком. Повторная генерация исключения осуществляется оператором Raise. Приведем общую схему такой двухэтапной обработки исключений:
    Try
      <Операторы внешнего блока.>
      Try
        <Операторы, при выполнении которых возможно исключение.>
      Except
      On <Тип исключения> Do
      Begin
       <Обработка исключений, сгенерированных во внутреннем блоке.>
       Raise;//Повторная генерация исключения.
      End;
      <Операторы внешнего блока. При возникновении исключения не выполняются.>
    Except
      <Обработка исключений и внутреннего, и внешнего блоков.>
    End;
    
  2. С помощью оператора Raise можно сгенерировать исключение любого типа в любом месте программы. Общий вид оператора Raise следующий:
        Raise <исключение>;    или
        Raise <тип исключения>.<конструктор>;    .
    

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

       If  Edit1.Text='' Then Raise EZeroDivide.Create ('Не задана 
                                              требуемая информация'); 
    

    если пользователь не задал требуемой информации, то будет сгенерировано исключение типа EZeroDivide (якобы целочисленное деление на нуль). При отсутствии обработчика этого исключения пользователь увидит на экране диалоговое окно с фразой: "Не задана требуемая информация". Так можно использовать предопределенные исключения для информации об ошибках, никакого отношения не имеющие к их первоначальному смыслу. Однако для этих целей лучше всего использовать созданные пользователем классы исключений, к рассмотрению которых мы приступаем.

    Как известно, классы исключений являются производными от класса Exception. Поэтому при создании нового класса данный класс нужно указывать в качестве родителя.

    Создаваемые классы можно разделить на две большие группы.

  1. Дочерний класс содержит только свойства и методы родительского класса. В этом случае достаточно описать новый класс:
        Type <имя класса исключения> = Class(Exception);
    
    и воспользоваться любым из перечисленных конструкторов для создания безымянного объекта данного класса. Например:
      .   .   .   .   .   .
    Type
      ENoInf = Class (Exception);//Создание нового класса.
      .   .   .   .   .   .
      //Генерация исключения.
      Raise ENoInf.Create('Не задана требуемая информация');
      .   .   .   .   .   .
      //Его обработка.
      On ENoInf Do MessageDlg ('Укажите цену товара.', 
                                             mtWarning, [mbOk], 0);
      .   .   .   .   .   .
    

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

    .   .   .   .   .   .
    S:='';
    If EditSer.Text='' Then S:='серию';//Проверка серии.
    If EditNom.Text='' Then //Проверка номера паспорта.
    If S='' Then S:='номер' Else S:=S+' и номер';
    If S<>'' Then Raise ENoInf.CreateFmt('Укажите %s паспорта',[S]);
    .   .   .   .   .   .
    
  2.    

  3. Дочерний класс содержит дополнительные поля. Определение такого класса будет иметь следующий вид:
    Type
      <имя класса исключения> = Class (Exception)
                                   <поля>
                                end;
    
    Например, объявление:
    Type
      EMy = Class (Exception)
              Public
                Enum: Integer;
            End;
    

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

      .   .   .   .   .   .
    Type
      EMy = Class (Exception)
              Public
                 Enum: Integer;
            End;
    Var  
        Exc: EMy; //Именованный объект исключения.
      .   .   .   .   .   .
    Try
    .   .   .   .   .   .
      If <условие наличия ошибки> Then
        Begin
          Exc:=EMy.Create(<текст сообщения>);
          Exc.Enum:=<идентификатор ошибки>;
          Raise Exc;//Генерация исключения.
        End;
    .   .   .   .   .   .
    Except
      On EMy Do
       Case Exc.Enum Of
          1: <набор действий 1>; 
          2: <набор действий 2>;
    .   .   .   .   .   .
       End;//Конец блока Case.
    End;//Конец блока Try.
    

    В заключение разберем исключение EAbort, несколько отличающееся от рассмотренных ранее. Генерация этого исключения также прерывает выполнение программы. Однако если оно не обрабатывается приложением, то разрушается без всяких дополнительных сообщений (без вывода диалогового окна с сообщением об ошибке).

   Простейший способ генерации этого исключения - вызов процедуры Abort:

  If <проверка условия прерывания> Then Abort; 

    Обычное применение EAbort - прерывание вычислений при выполнении некоторого условия окончания или нажатие какой-либо комбинации клавиш. Таким образом, генерация исключения процедурой Abort эквивалентна применению Exit или Break, с той только разницей, что Break прерывает выполнение цикла и управление передается следующему за циклом оператору; Exit прерывает выполнение текущей процедуры и управление передается в вызвавшую ее процедуру, а Abort прерывает текущую процедуру и все вызвавшие ее процедуры. При необходимости перехватить исключение на каком-то промежуточном уровне, расположив там блок Try...Except и вставив туда оператор On следующего вида:

    On EAbort Do ....; 

    На следующем шаге мы рассмотрим содержимое пункта меню View.




Предыдущий шаг Содержание Следующий шаг