「7.Delphi应用程序框架」2.单元文件
2.单元文件
在 Delphi 中,最常使用的最重要的源代码文件就是单元文件。单元是模块化编程的基础,Delphi中的类就是建立在单元文件基础上的。单元不仅仅能定义窗体,还可以定义各种例程。
2.1单元文件的构成
单元文件由如下几个部分构成:
- Interface
接口部分,用于声明对其他单元可访问的内容。
- Implementation
实现部分,具体实现功能的代码。
- Initialization
初始化部分,用于执行初始化功能,可选部分
- Finalization
结束部分,执行程序终止功能,可选部分
单元结构例子:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TForm1 = class(TForm)
procedure FormActivate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormActivate(Sender: TObject);
begin
//
end;
initialization
finalization
end.
说明:
1.interface 中的uses 语句指明本单元中引用的单元文件,单元文件之间用逗号分隔。一般由 Delphi 自动维护。如果需要引用其他单元,可以手动添加到 uses 语句中。
2.implementation 中的 uses 语句定义了程序实现部分引用的单元文件。
2.2单元的组成部分
2.2.1 Unit 语句
Unit 语句中包含了文件的名称。
单元名除了作为文件名使用外,还有一个用途:作为定义命名空间的机制。如:在一个单元名为demo的单元中有一个过程叫myTest,在另一个sysset的单元中也有一个myTest过程,为了区分这两个过程,在调用过程时,可以使用单元名作为前缀。
unit语句格式:
unit 单元名
注意:单元名与主文件名同名。
2.2.2 接口部分
起始于关键字 interface ,结束于 implementation 之前。
接口部分描述应用程序的其余部分在该单元中可以访问的内容。接口部分没有运行代码,包含了其他单元可以访问的类型、常量、变量等,也描述了该单元中可调用的过程和可使用的函数。
2.2.3 实现部分
实现部分主要是编写运行代码的,也可以包含类型定义、变量声明和常量。
定义在接口部分的类型、变量和常量可以在单元外使用,定义在实现部分的只能在本单元中使用。
过程和函数的声明一般防止接口部分,过程和函数的定义一般放在实现部分。
定义在实现部分的过程和函数,如果在接口部分没有声明,则只能在本单元中使用,如果希望其他单元也可以访问过程和函数,则应该将其声明放在接口部分。
2.2.4 uses 语句
uses 语句指示编译器在列出的单元中查找代码,该语句既可以在接口部分出现,也可以在实现部分出现。uses 语句必须紧跟在 interface 或 implementation 关键字之后。
对于两个单元的相互引用,不能在接口部分进行相互引用,因为这样会导致循环引用,但在实现部分可以相互引用。
所有单元都隐式引用了 system.pas 单元,该单元无法显式引用。
示例:
Unit1.pas
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, unit2;
type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
end.
Unit2.pas
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, unit1;
type
TForm2 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
uses
unit1;
{$R *.dfm}
end.
在上面的代码中,我们在unit1中的接口部分的 uses 中添加了 unit2,同时在 unit2 的接口部分的 uses 中添加 unit1,然后进行项目编译,会出现:
[dcc32 Fatal Error] Unit2.pas(7): F2047 Circular unit reference to 'Unit1'
2.2.5 type 语句
接口部分和实现部分都可以有 type 语句,一般情况下,type 语句都是位于接口部分。
2.2.6 变量部分
接口部分和实现部分都可以有 var 语句。
当要定义其他单元可访问的变量时,将变量声明写在接口部分,然后在要使用变量的其他单元的 uses 语句中包含该单元即可。
接口部分定义的变量可以认为是全局变量,要谨慎使用。
实现部分定义的变量只能在本单元中使用,这种变量称为本地变量。
2.2.7 资源声明
在项目文件的代码中可以看到 {$R *.res} 编译器指令,该指令指示编译器包含与该单元同名的 res 文件。$R 指令通常只出现在具有窗体的单元中。
2.2.8 初始化部分
单元的 initialization 部分的代码将在单元中任何其他代码执行之前执行。这部分代码在单元向内存加载时运行。如果需要使用全局变量或本地变量,可以在 initialization 关键字之后进行初始化。
2.2.9 结束部分
单元中 finalization 关键字之后的代码为结束部分,一般在 finalization 部分执行清除代码,并释放在 initialization 部分分配给对象的内存。finalization 部分与对应的 initialization 部分按相反的顺序运行,如:Unit1、Unit2、Unit3 按顺序载入内存,则其 finalization 部分将按 Unit3、Unit2、Unit1的顺序运行。
2.3单元的创建
创建单元和创建窗体之间是没有关系的,一般情况下,当我们创建窗体时,会自动创建一个单元,但也可以使用菜单 File / New,然后选择 Unit 来创建单元。如:新创建一个单元的代码如下
unit Unit3;
interface
implementation
end.
单元的接口部分可以声明不同的成员,包括:函数、过程、全局变量、类型等。当创建一个窗体时,单元中唯一的元素是窗体数据类型的定义 TFormn 和 该类型的一个全局变量 Formn,如:
type
TForm2 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
单元中仍可以用普通的单元、函数和过程,也可以包含未引用的窗体和其他成员的类。