对象和引用的区别是什么?

42

什么是两者之间的区别?

TFuncOfIntToString = reference to function(x: Integer): string; 

TFuncOfIntToString = function(x: Integer): string of object; 

我使用对象的of属性

2个回答

97

让我们考虑以下三种类型声明:

TProcedure = procedure;
TMethod = procedure of object;
TAnonMethod = reference to procedure;

这些都非常相似。在调用这三种类型的实例时,调用代码是相同的。差异在于可以分配给这些类型变量的内容。
程序类型
TProcedure 是一种过程类型。您可以将类似以下形式的内容分配给类型为 TProcedure 的变量:
procedure MyProcedure;
begin
end;

这是一个非面向对象的过程。你不能将实例或类方法赋给TProcedure变量。但是,你可以将静态类方法赋给TProcedure变量。 方法指针 TMethod是一个方法指针,它通过of object来表示。当你有一个TMethod类型的变量时,你必须分配以下之一:
  1. 已实例化对象的实例方法;或者
  2. 类方法。
因此,你可以分配以下任一内容:
procedure TMyClass.MyMethod;
begin
end;

class procedure TMyClass.MyClassMethod;
begin
end;

过程类型和方法指针之间的主要区别在于,后者包含对代码和数据的引用。方法指针通常被称为双指针过程类型。包含方法指针的变量包含对要调用的代码和实例/类的引用。

考虑以下代码:

var
  instance1, instance2: TMyClass;
  method1, method2: TMethod;
....
method1 := instance1.MyMethod;
method2 := instance2.MyMethod;

现在,虽然method1method2引用相同的代码段,但它们与不同的对象实例相关联。因此,如果我们调用
method1();
method2();

我们正在两个不同的实例上调用MyMethod。该代码等效于:
instance1.MyMethod();
instance2.MyMethod();

匿名方法

最后我们来到匿名方法。它们比过程类型和方法指针更加通用。您可以将以下任何内容分配给使用引用到语法定义的变量:

  1. 一个普通的非面向对象过程。
  2. 已实例化类的实例方法。
  3. 一个类方法。
  4. 一个匿名方法。

例如:

var
  AnonMethod: TAnonMethod;
....
AnonMethod := MyProcedure;            // item 1 above
AnonMethod := instance1.MyMethod;     // item 2
AnonMethod := TMyClass.MyClassMethod; // item 3

匿名方法,即上面提到的第4种方法,是在代码中内联声明的方法。例如:

var
  AnonMethod: TAnonMethod;
....
AnonMethod := procedure
  begin
    DoSomething;
  end;

匿名方法相比于过程类型和方法指针的最大优势在于它们允许变量捕获。例如,考虑以下简短的程序以说明:
{$APPTYPE CONSOLE}
program VariableCapture;

type
  TMyFunc = reference to function(X: Integer): Integer;

function MakeFunc(Y: Integer): TMyFunc;
begin
  Result := function(X: Integer): Integer
    begin
      Result := X*Y;
    end;
end;

var
  func1, func2: TMyFunc;

begin
  func1 := MakeFunc(3);
  func2 := MakeFunc(-42);
  Writeln(func1(4));
  Writeln(func2(2));
  Readln;
end.

这将产生以下输出:
12
-84

16
我还没看到底部,为什么我就知道是你发的信息? - Marjan Venema
1
@MarjanVenema 可能是因为 David 是为 Delphi 标签在 SO 上提供了一个基础模块的极少数人之一,他给出了详细的解释。(: - user497849
6
@ComputerSaysNo,谢谢你,但是当你说“很少”的时候,我不完全同意你的看法。我认为在这里有一些活跃的Delphi回答者,他们提供了良好的解释。我不会点名,但是那些在这里活跃的人都知道他们是谁。我们应该通过投票来鼓励那些附带解释的答案。 - David Heffernan
4
那是一个非常好的回答。 - Nick Hodges
2
谢谢@Nick,虽然我不确定伟大。个人而言,我有点难过,因为还没有人发现我的彩蛋:http://stackoverflow.com/questions/14932549/chr-equivalent-for-unicode-in-delphi-7/14932710#14932710 - David Heffernan

9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接