違いは何ですか
TFuncOfIntToString = reference to function(x: Integer): string;
と
TFuncOfIntToString = function(x: Integer): string of object;
オブジェクトの
違いは何ですか
TFuncOfIntToString = reference to function(x: Integer): string;
と
TFuncOfIntToString = function(x: Integer): string of object;
オブジェクトの
次の3つの型宣言について考えてみましょう。
TProcedure = procedure;
TMethod = procedure of object;
TAnonMethod = reference to procedure;
これらはすべて互いに非常に似ています。これら3つのタイプのそれぞれのインスタンスを呼び出すという点では、呼び出しコードは同じです。これらのタイプの変数に割り当てることができるものに違いが生じます。
手続き型
TProcedure
手続き型です。次の形式のタイプの変数に割り当てることができますTProcedure
。
procedure MyProcedure;
begin
end;
これは非オブジェクト指向の手順です。TProcedure
インスタンスまたはクラスのメソッドを変数に割り当てることはできません。ただし、静的クラスメソッドをTProcedure
変数に割り当てることができます。
メソッドポインタ
TMethod
メソッドポインタです。これは、の存在によって示されof object
ます。タイプの変数がある場合は、次のTMethod
いずれかを割り当てる必要があります。
したがって、次のいずれかを割り当てることができます。
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;
現在、method1
とmethod2
は同じコードを参照していますが、それらは異なるオブジェクトインスタンスに関連付けられています。だから、私たちが呼ぶなら
method1();
method2();
MyMethod
2つの異なるインスタンスを呼び出しています。そのコードは次のものと同等です。
instance1.MyMethod();
instance2.MyMethod();
匿名メソッド
最後に、匿名メソッドについて説明します。これらは、手続き型やメソッドポインタよりもさらに汎用的です。reference to
構文を使用して定義された変数に、次のいずれかを割り当てることができます。
例えば:
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