2 创建自己的异常类
异常机制是完全融入面向对象的体系的,所以异常类和一般类一样具有继承和多态的
3
性质。其实,异常类和普通类并没有什么区别。
Object Pascal的运行时异常基类是 Exception,VCL中所有异常类都应该从它派生。当
然,Object Pascal 语言并不规定如此,可以用 raise 抛出任何除简单类型之外的类类型的对
象,try…except 同样可以捕获它,在异常处理后同样会自动析构、回收它,只是 Exception
定义了异常的大多数特征。既然别人已经为我们准备了一个好用的、完备的 Exception,当
然没有理由不用它。
也许读者也已经注意到,所有 VCL 的异常发生时,弹出的警告对话框都带有一段有价
值的对于异常的发生原因的描述(正如图 3.1 中的“"is not a valid integer value”)。这段
描述对于 debug 工作是非常有用的。它正是来自于 Exception 类的 Message属性,所有异常
类被创建时都必须给出一个出错描述。因此,在定义、使用自己的异常类时,也要给出一
个不会令人迷惑的、明白说出错误原因的 Message 属性。 注意:从 Exception派生自己的异常类!
下面以一个示例程序来演示如何定义、使用自己的异常类,其代码及可执行文件可在
配书光盘的 exception 目录下找到。
程序运行后的界面如图 3.2 所示。
图3.2 自定义异常类演示程序界面
该程序的运行界面十分充分地体现了第 1 章所说的“简单性”原则。界面上只有 3 个
按钮,先看上面两个(另一个“try…finally”按钮先不说明,留待 3.3 节讲解)。一个模拟
打开文件时发生“找不到文件”的错误,一个模拟发生“文件格式错”的错误。所谓模拟
发生错误,就是在并没有真正发生错误的情况下抛出异常,使得编译器认为发生了错误,
即单击这两个按钮后,程序会分别抛出相应的异常。
首先要定义两种错误所对应的异常类。它们的定义和实现在 ExceptionClass.pas 单元
中。该单元代码清单如下:
·53·
Delphi 高手突破
unit ExceptionClass;
interface
uses SysUtils, Dialogs;
Type
EFileOpenFailed = class(Exception) // 定义一个文件打开失败的通用异常类
public
procedure Warning(); virtual; abstract;
end;
EFileNotFound = class(EFileOpenFailed) // 细化文件打开失败的异常
public
procedure Warning(); override;
end;
EFileFormatErr = class(EFileOpenFailed) // 细化文件打开失败的异常
public
procedure Warning(); override;
end;
implementation
{ EFileNotFound }
procedure EFileNotFound.Warning;
begin
ShowMessage('真是不可思议,竟然找不到文件!');
end;
{ EFileFormatErr }
procedure EFileFormatErr.Warning;
begin
ShowMessage('更不可思议的是,文件格式不对!');
end;
end.
我们先定义了一个标志打开文件失败的异常基类 EFileOpenFailed,并给它声明了一个
·54·
异常及错误处理
抽象方法 Warning。然后又细化了错误的原因,从而派生出两个异常类——EFileNotFound、
EFileFormatErr,它们都具体实现了 Warning 方法。
在应用程序的主Form(Form1)中,定义一个模拟发生错误并抛出异常的SimulateError()
方法来模拟发生错误、抛出异常。
然后定义一个 ToDo()方法来调用会引发异常的 SimulateError(),并且用 Try 将其捕获
进行异常处理。
3
最后在两个按钮的 OnClick()事件中,调用 ToDo()方法。
其代码清单如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Label1: TLabel;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure SimulateError(Button : TObject);
procedure ToDo(Button : TObject);
end;
var
Form1: TForm1;
implementation
uses ExceptionClass;
·55·
Delphi 高手突破
{$R *.dfm