全國(guó)計(jì)算機(jī)等級(jí)考試二級(jí)Delphi輔導(dǎo)講義 123

字號(hào):

12.3.5 自定義異常類的應(yīng)用
    利用Delphi的異常類機(jī)制我們可以定義自己的異常類來處理程序執(zhí)行中的異常情況。同標(biāo)準(zhǔn)異常不同的是:這種異常情況并不是相對(duì)于系統(tǒng)的正常運(yùn)行,而是應(yīng)用程序的預(yù)設(shè)定狀態(tài)。比如輸入一個(gè)非法的口令、輸入數(shù)據(jù)值超出設(shè)定范圍、計(jì)算結(jié)果偏離預(yù)計(jì)值等等。
    使用自定義異常需要:
    1.自己定義一個(gè)異常對(duì)象類;
    2.自己引發(fā)一個(gè)異常。
    12.3.5.1 定義異常對(duì)象類
    異常是對(duì)象,所以定義一類新的異常同定義一個(gè)新的對(duì)象類型并無(wú)太大區(qū)別。由于缺省異常處理只處理從Exception或Exception子類繼承的對(duì)象,因而自定義異常類應(yīng)該作為Exception或其它標(biāo)準(zhǔn)異常類的子類。這樣,假如在一個(gè)模塊中引發(fā)了一個(gè)新定義的異常,而這個(gè)模塊并沒有包含對(duì)應(yīng)的異常響應(yīng),則缺省異常處理機(jī)制將響應(yīng)該異常,顯示一個(gè)包含異常類名稱和錯(cuò)誤信息的消息框。
    下面是一個(gè)異常類的定義:
    type
    EMyException = Class(Exception) ;
    12.3.5.2 自引發(fā)異常
    引發(fā)一個(gè)異常,調(diào)用保留字raise,后邊跟一個(gè)異常類的實(shí)例。
    假如定義:
    type
    EPasswordInvalid = Class(Exception);
    則在程序中如下的語(yǔ)句將引發(fā)一個(gè)EPasswordInvalid異常:
    If Password <> CorrectPassword then
    raise EPasswordInvalid.Create('Incorrect Password entered');
    異常產(chǎn)生時(shí)把System庫(kù)單元中定義的變量ErrorAddr的值置為應(yīng)用程序產(chǎn)生異常處的地址。在你的異常處理過程中可以引用ErrorAddr的值。
    在自己引發(fā)一個(gè)異常時(shí),同樣可以為ErrorAddr分配一個(gè)值。
    為異常分配一個(gè)錯(cuò)誤地址需要使用保留字at,使用格式如下:
    raise EInstance at Address_Expession;
    12.3.5.3 自定義異常的應(yīng)用舉例
    下面我們給出一個(gè)利用自定義異常編程的完整實(shí)例。
    兩個(gè)標(biāo)簽框(Label1、Label2)標(biāo)示對(duì)應(yīng)編輯框的功能。編輯框PassWord和InputEdit用于輸入口令和數(shù)字。程序啟動(dòng)時(shí)Label2、InputEdit不可見。當(dāng)在PassWord中輸入正確的口令時(shí),Label2、InputBox出現(xiàn)在屏幕上。此時(shí)Label1、PassWord隱藏。
    設(shè)計(jì)時(shí),令Label2、InputEdit的Visible屬性為False。通過設(shè)置PassWord的PassWordChar可以確定輸入口令時(shí)回顯在屏幕上的字符。
    自定義異常EInvalidPassWord和EInvalidInput分別用于表示輸入的口令非法和數(shù)字非法。它們都是自定義異常EInValidation的子類。而EInValidation直接從Exception異常類派生。
    下面是三個(gè)異常類的定義。
    type
    EInValidation = class(Exception)
    public
    ErrorCode: Integer;
    constructor Create(Const Msg: String;ErrorNum: Integer);
    end;
    EInvalidPassWord = class(EInValidation)
    public
    constructor Create;
    end;
    EInvalidInput = class(EInValidation)
    public
    constructor Create(ErrorNum: Integer);
    end;
    EInValidation增加了一個(gè)公有成員ErrorCode來保存錯(cuò)誤代碼。錯(cuò)誤代碼的增加提供了很大的編程靈活性。對(duì)于異常類,可以根據(jù)錯(cuò)誤代碼提供不同的錯(cuò)誤信息;對(duì)于使用者可以通過截取錯(cuò)誤代碼,在try…except模塊之外來處理異常。
    從以上定義可以發(fā)現(xiàn):EInvalidPassWord和EInvalidInput的構(gòu)造函數(shù)參數(shù)表中沒有表示錯(cuò)誤信息的參數(shù)。事實(shí)上,它們保存在構(gòu)造函數(shù)內(nèi)部。下面是三個(gè)自定義異常類構(gòu)造函數(shù)的實(shí)現(xiàn)代碼。
    constructor EInValidation.Create(Const Msg: String; ErrorNum: Integer);
    begin
    inherited Create(Msg);
    ErrorCode := ErrorNum;
    end;
    constructor EInValidPassWord.Create;
    begin
    inherited Create('Invalid Password Entered',0);
    end;
    constructor EInValidInput.Create(ErrorNum: Integer);
    var
    Msg: String;
    begin
    case ErrorNum of
    1:
    Msg := 'Can not convert String to Number';
    2:
    Msg := 'Number is out of Range';
    else
    Msg := 'Input is Invalid';
    end;
    inherited Create(Msg,ErrorNum);
    end;
    對(duì)于EInvalidInput,ErrorCode=1表示輸入的不是純數(shù)字序列,而ErrorCode=2表示輸入數(shù)值越界。
    口令檢查是用戶在PassWord中輸入口令并按下回車鍵后開始的。實(shí)現(xiàn)代碼在PassWord的OnKeyPress事件處理過程中:
    procedure TForm1.PassWordKeyPress(Sender: TObject; var Key: Char);
    const
    CurrentPassWord = 'Delphi';
    begin
    if Key = #13 then
    begin
    try
    if PassWord.text <> CurrentPassWord then
    raise EInvalidPassWord.Create;
    Label2.Visible := True;
    InputEdit.Visible := True;
    InputEdit.SetFocus;
    PassWord.Visible := False;
    Label1.Visible := False;
    except
    on EInvalidPassWord do
    begin
    PassWord.text := '';
    raise;
    end;
    end;
    Key:=#0;
    end;
    end;
    同樣,在InputEdit的OnKryPress事件處理過程中實(shí)現(xiàn)了輸入數(shù)字的合法性檢查:
    procedure TForm1.InputEditKeyPress(Sender: TObject; var Key: Char);
    var
    Res: Real;
    Code: Integer;
    begin
    if Key = #13 then
    begin
    try
    val(InputEdit.text,Res,Code);
    if Code <> 0 then
    raise EInValidInput.create(1);
    if (Res > 1) or (Res < 0) then
    raise EInValidInput.create(2);
    MessageDlg('Correct Input', mtInformation,[mbOk], 0);
    Key := #0;
    except
    on E:EInValidInput do
    begin
    InputEdit.text := '';
    MessageDlg(E.Message, mtWarning,[mbOk], 0);
    end;
    end;
    end;
    end;
    由于異常響應(yīng)后即被清除,所以要顯示異常信息,需要另外的手段。在以上兩段程序中我們采用了兩種不同的方法:在口令合法性檢查中,利用異常重引發(fā)由系統(tǒng)進(jìn)行缺省響應(yīng);在輸入數(shù)字合法性檢查中,通過異常實(shí)例來獲取異常信息并由自己來顯示它。
    以上所舉的是一個(gè)非常簡(jiǎn)單的例子,但從中已可以發(fā)現(xiàn):使用自定義異常編程,為程序設(shè)計(jì)帶來了很大的靈活性。