问题描述
在阅读Anonymous Methods in Delphi上的文档时,我开始感到奇怪。我一直使用这样的东西:
type TMathFn = Function(A,B: Integer): Integer;
var fn: TMathFn;
总是为我工作。但是此文档告诉我改用它:
type TMathFn = Reference to Function(A,B: Integer): Integer;
var fn: TMathFn;
从1994年到2010年,我一直在Delphi中进行开发,因此我对“参考”部分不熟悉。不过,这两种选择似乎都可以正常工作。所以...
它们相同吗?
解决方法
“ REFERENCE TO”允许使用匿名方法(过程/功能的内联定义),该方法可以捕获上下文(例如,本地变量,将其捕获为引用,即,如果在捕获后更改了变量,则为捕获的修改后的值,请参见下文。)
TYPE TMyProc = REFERENCE TO PROCEDURE(CONST S : STRING);
PROCEDURE Information(CONST S : STRING);
BEGIN
MessageDlg(S,mtInformation,[mbOK],0)
END;
PROCEDURE RunProc(P : TMyProc ; CONST S : STRING);
BEGIN
P(S)
END;
PROCEDURE A(B,C : INTEGER);
VAR
D : INTEGER;
P : TMyProc;
BEGIN
D:=3;
// D is 3 at the time of capture
P:=PROCEDURE(CONST S : STRING)
BEGIN
Information(S+': '+IntToStr(D)+' -> '+IntToStr(B))
END;
// D is now 4 - and is reflected in the captured routine,as
// the capture is done by REFERENCE and not by VALUE.
INC(D);
RunProc(P,'Hello')
END;
BEGIN
A(2,3)
END.
在消息框中将显示“ Hello:4-> 2”。
P的上述定义“捕获”(包括)变量D和B,因此即使将其传递给不存在这些变量的另一个函数,您仍然可以访问它们。
(普通)PROCEDURE [OF OBJECT]类型几乎是不可能的,因为它们无法访问在执行时声明的局部变量。
,不,它们不相同。
不同之处在于
TMathFn = function(A,B: Integer): Integer;
是一个普通函数,
TMathMethod = function(A,B: Integer): Integer of object;
是一种方法,
TMathAnonMethod = reference to function(A,B: Integer): Integer;
是匿名方法,但是您也可以将普通函数或方法分配给该类型的变量。
例如,如果
type
TMathFn = function(A,B: Integer): Integer;
TMathMethod = function(A,B: Integer): Integer of object;
TMathAnonMethod = reference to function(A,B: Integer): Integer;
function Test(A,B: Integer): Integer;
begin
Result := A + B;
end;
type
TTestClass = class
function Test(A,B: Integer): Integer;
end;
{ TTestClass }
function TTestClass.Test(A,B: Integer): Integer;
begin
Result := A + B;
end;
然后适用以下条件:
procedure TForm1.FormCreate(Sender: TObject);
var
T: TTestClass;
F: TMathFn;
M: TMathMethod;
AM: TMathAnonMethod;
begin
T := TTestClass.Create;
try
F := Test; // compiles
F := T.Test; // doesn't compile
F := function(A,B: Integer): Integer
begin
Result := A + B;
end; // doesn't compile
M := Test; // doesn't compile
M := T.Test; // compiles
M := function(A,B: Integer): Integer
begin
Result := A + B;
end; // doesn't compile
AM := Test; // compiles
AM := T.Test; // compiles
AM := function(A,B: Integer): Integer
begin
Result := A + B;
end; // compiles
finally
T.Free;
end;
end;
在后台,您可能已经知道,F
只是一个(函数)指针,而M
是一个method pointer。另一方面,匿名方法则具有更多的基于接口的实现,这允许其发挥所有魔力(如变量捕获)。