Procedural types(过程类型)
Procedural types: Overview(概述)
过程类型允许你把过程和函数作为“值”看待,它可以赋给变量或传给其它过程和函数。比如,假设你
定义了一个叫做Calc 的函数,它有两个整型参数并返回一个整数值:
function Calc(X,Y: Integer): Integer;
你可以把Calc 函数赋给变量F:
var F: function(X,Y: Integer): Integer;
F := Calc;
我们只取过程或函数头(heading)并把procedure 或function 后面的标志符去掉,剩下的就是过程类型
的名称。你可以在声明变量时直接使用这样的名称(就像上面的例子一样),也可以声明新类型:
type
TIntegerFunction = function: Integer;
Data types, variables and constants
- 65 -
TProcedure = procedure;
TStrProc = procedure(const S: string);
TMathFunc = function(X: Double): Double;
var
F: TIntegerFunction; {F 是一个无参数、返回整数值的函数}
Proc: TProcedure; { Proc 是一个无参数过程}
SP: TStrProc; { SP 是一个使用string 类型参数的过程}
M: TMathFunc; { M 是一个使用Double 类型参数、返回Double 值的函数}
procedure FuncProc(P: TIntegerFunction); { FuncProc 是一个过程,它的参数是
一个无参数、返回整数值的函数}
上面的所有变量都是过程指针,也就是指向过程或函数地址的指针。若想引用一个实例对象的方法(参
考Classes and objects),你需要在过程类型的名称后面加上of object。比如
type
TMethod = procedure of object;
TNotifyEvent = procedure(Sender: TObject) of object;
这些类型表示方法指针。方法指针实际上是一对指针:第一个存储方法的地址,第二个存储方法所属的
对象的引用。给出下面的声明
type
TNotifyEvent = procedure(Sender: TObject) of object;
TMainForm = class(TForm)
procedure ButtonClick(Sender: TObject);
...
end;
var
MainForm: TMainForm;
OnClick: TNotifyEvent
我们就可以进行下面的赋值:
OnClick := MainForm.ButtonClick;
两个过程类型是兼容的,如果它们具有
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//弄明白这一点, 才好使用回调函数
{定义方法类型}
type
TFunType = function(x: Integer): Integer; {函数类型}
TProcType = procedure(name: string); {过程类型}
{定义一个符合 TFunType 类型的函数}
function MyFun(x: Integer): Integer;
begin
Result := x * 2;
end;
{定义一个符合 TProcType 类型的过程}
procedure MyProc(name: string);
begin
ShowMessage('我是' + name);
end;
{使用}
procedure TForm1.Button1Click(Sender: TObject);
var
Fun : TFunType; {定义一个 TFunType 类型的变量}
Proc: TProcType; {定义一个 TProcType 类型的变量}
begin
Fun := MyFun; {让变量 Fun 指向和它具有同样参数和返回值的自定义函数 MyFun}
Proc := MyProc; {让变量 Proc 指向和它具有同样参数的自定义过程 MyProc}
{现在这两个方法的变量 Fun、Proc 可以使用了}
ShowMessage(IntToStr(Fun(4))); {8}
Proc('万一'); {我是万一}
end;
//把一个方法当作另一个方法的参数, 就是回调方法, 大家习惯称作回调函数
type
TFunType = function(i: Integer): Integer; {声明一个方法类型}
function MyFun(i: Integer): Integer; {建立类型兼容的函数}
begin
Result := i*2;
end;
{把函数当作参数, 再定义一个函数}
function MyTest(x: Integer; F: TFunType): Integer;
begin
Result := F(x);
end;
{测试}
procedure TForm1.Button1Click(Sender: TObject);
var
Fun: TFunType; {声明一个 TFunType 的变量}
i: Integer;
begin
Fun := MyFun; {让方法变量 Fun 指向和它类型兼容的一个方法}
{测试 Fun; Fun 是一个方法变量, 现在去执行那个方法, 它就可以当作那个方法来使用了}
i := Fun(4);
ShowMessage(IntToStr(i)); //8
{把 Fun 当作参数使用; 把函数当作参数使用, 这就是回调函数}
i := MyTest(4,Fun);
ShowMessage(IntToStr(i)); //8
end;