单元
虽然所有窗体都在单元中定义,但反之则不然。除窗体外,单元中还可以定义一系列能访问的例程。选择File > New菜单命令,然后在Object Repository的New 页中选择Unit 图标,随即当前工程中就会加入一个空白单元。单元代码分区存放,空白单元的代码如下:
unit Unit1;
interface
implementation
end.
单元的概念比较简单,单元名与文件名相同,而且必须唯一。单元包括界面区(interface)及实现区(implementation),界面区用于声明其它单元能看到的部分;实现区存放界面的实现代码及外部不可见的声明。此外还有两个可选的区,即初始化区及结束区,其中初始化区存放初始化代码,当程序加载到内存时执行;结束区存放程序终止时执行的代码。
单元总体结构如下:
unit unitName;
interface
// other units we need to refer to
uses
A, B, C;
// exported type definition
type
newType = TypeDefinition;
// exported constants
const
Zero = 0;
// global variables
var
Total: Integer;
// list of exported functions and procedures
procedure MyProc;
implementation
uses
D, E;
// hidden global variable
var
PartialTotal: Integer;
// all the exported functions must be coded
procedure MyProc;
begin
// ... code of procedure MyProc
end;
initialization
// optional initialization part
finalization
// optional clean-up code
end.
界面区头部的uses子句表示需要访问的外部单元,这些外部单元中定义了你需要引用的数据类型,如自定义窗体内所用的控件。
实现区头部的uses子句用于表示只在实现部分访问的单元。如果例程或方法的代码需要引用其他单元,你应该把这些单元加到实现区子句中,而不是界面区。你所引用的单元必须在工程文件目录中能到,或在工程选项对话框的 Directories/Conditionals 页设定这些单元的搜索路径。
C++程序员应该知道uses语句和include 指令是不同的。uses语句只是用于输入引用单元的预编译界面部分,引用单元的实现部分在单元编译时才考虑。你引用的单元可以是源代码格式(PAS),也可以是编译格式(DCU),但是必须用同一版本的Delphi进行编译。
在单元的界面区中可以声明许多不同的元素,包括过程、函数、全程变量及数据类型。在Delphi 应用程序中,数据类型可能用得最频繁。每创建一个窗体,Delphi 会在单元中自动建立一个新的数据类型--类(class)。在Delphi 单元中不仅能定义窗体;还能象传统单元一样,只包含过程及函数;还可以定义与窗体和任何可视控件无关的类。
单元的工作空间
Pascal单元是封装性和可视性的关键,它很可能比类中的 private 和 public 关键字还要重要。(实际上,private关键字与类单元的工作空间有关)。一个标识符(如一个变量、过程、函数或数据类型)的工作空间是指能访问标识符的代码段。基本原则是:标识符在它工作空间内才有意义,也就是说,只在其声明的代码块中才有意义,在工作空间外你不能访问这些标识符。例如:
∙ 局部变量:如果你在例程或方法代码块内声明一个变量,那么单元外部不能访问这个变量。该标识符的工作空间就是定义标识符的整个例程,其中包括嵌套例程(除非嵌套例程内有一个同名标识符覆盖了外部定义)。当调用到例程时,其变量压入栈内存中,例程一结束,栈中的内存就自动释放。
∙ 全程隐藏变量:如果你在单元的实现部分声明一个标识符,那么在单元外你不能使用它,但是能在单元内任一代码块及过程中使用它。程序一启动就会为全程隐藏变量分配内存,程序终止内存释放,你可以在单元初始化区给它赋初值。
∙ 全程变量:如果你在单元的界面部分声明标识符,那么该标识符的工作空间就扩大了,任何Use它的单元都能访问它。这类变量的内存分配及生命周期与上类变量相同,唯一不同的
是其可见性。
只要程序单元的uses子句中列出某一单元名,那么所列单元界面区中声明的任何标识符该程序都能访问。窗体类的变量就是这样声明的,所以你可以在其他窗体代码中访问这个窗体以及它的公共域、方法、属性和组件。当然把什么都声明为全局标识这种编程习惯并不好。除了明显的内存消耗问题外,使用全程变量使代码维护和更新变得困难。一句话,你应该尽量少用全程变量。
单元用作命名空间
uses 语句是访问其他单元工作空间的标准技术,通过该语句你能访问其它单元的定义内容。如果恰巧两个单元声明的标识符同名,也就是说你可能有两个同名的类或例程,遇到这种情况,你可以用单元名作前缀定义类型或过程名,由此进行区分。例如用Totals.ComputeTotal访问Totals 单元中的ComputeTotal 过程。不过这种情况最好不要经常遇到,因此强烈建议不要在同一程序中用同一名字表示两个不同的东西。
然而,如果查阅VCL库和Windows 文件,你会发现一些Delphi 函数和Delphi 可用的Windows API 函数同名,不过参数往往不同,下面以Beep 过程为例说明这个问题。
新建一个Delphi 程序,添加一个按钮,然后写入以下代码:
procedure TForm1.Button1Click(Sender: TObject);
begin
Beep;
end;
执行程序,单击按钮,你会听到一个短促的声音。现在移到单元的uses语句,把原先的代码:
uses
Windows, Messages, SysUtils, Classes, ...
改为下面的样式,只要把SysUtils单元移到Windows之前:
uses
SysUtils, Windows, Messages, Classes, ...
现在如果重新编译这段代码,你会得到一个编译错误:”Not enough actual parameters”(实际参数不够)。问题在于Windows 单元定义了另一个带两个参数的Beep 函数。应该说uses子句中第一个单元的定义被后面单元的定义覆盖,解决方法很简单:
procedure TForm1.Button1Click(Sender: TObject);
begin
SysUtils.Beep;
end;
不管uses子句中单元顺序如何排列,以上代码都能编译通过。在Delphi中很少有其他命名冲突的情况,因为Delphi 代码通常放在类的方法中,如果不同类中有两个同名的方法不会产生任何冲突,只是使用全程例程会产生冲突问题。
单元和程序
Delphi 应用程序源代码文件可分成两类,它们是一个或多个单元文件及一个程序文件,单元文件可以看成是次一级的文件,它被应用程序的主体——程序文件——引用。理论上如此,实际上程序文件通常是自动产生的,作用有限,程序启动并运行主窗体时才会用到它。程序文件的代码,或说Delphi 工程文件(DPR),可用手工进行编辑,也可通过工程管理器及其与应用程序、窗体相关的选项进行编辑。
程序文件的结构通常比单元文件的结构简单得多。下面是一个程序文件的源代码:
program Project1;
uses
Forms,
Unit1 pascal语言还有人用吗in Unit1.PAS� {Form1DateForm};
begin
Application.Initialize;
Application.CreateForm (TForm1, Form1);
Application.Run;
end.
从上可见,文件中只有一个uses区和应用程序的主体代码,主体代码包含在begin 和 end 关键字之间。程序的uses子句特别重要,因为需要通过它来管理应用程序的编译和连接。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论