40

違いは何ですか

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

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

オブジェクトの

4

2 に答える 2

92

次の3つの型宣言について考えてみましょう。

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

これらはすべて互いに非常に似ています。これら3つのタイプのそれぞれのインスタンスを呼び出すという点では、呼び出しコードは同じです。これらのタイプの変数に割り当てることができるものに違いが生じます。

手続き型

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;

手続き型とメソッドポインタの大きな違いは、後者にはコードとデータの両方への参照が含まれていることです。メソッドポインタは、多くの場合、2ポインタ手続き型として知られています。メソッドポインタを含む変数には、コードへの参照と、それを呼び出すインスタンス/クラスが含まれています。

次のコードを検討してください。

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

現在、method1method2は同じコードを参照していますが、それらは異なるオブジェクトインスタンスに関連付けられています。だから、私たちが呼ぶなら

method1();
method2();

MyMethod2つの異なるインスタンスを呼び出しています。そのコードは次のものと同等です。

instance1.MyMethod();
instance2.MyMethod();

匿名メソッド

最後に、匿名メソッドについて説明します。これらは、手続き型やメソッドポインタよりもさらに汎用的です。reference to構文を使用して定義された変数に、次のいずれかを割り当てることができます。

  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
于 2013-02-20T09:10:33.833 に答える
8

1 つ目は無名メソッド、2 つ目は通常メソッドです。

于 2013-02-20T08:39:04.813 に答える