2013-02-20 122 views

回答

72

讓我們考慮以下三種類型聲明:

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

這些都是非常相似對方。對於這三種類型的每一種的調用實例而言,調用代碼是相同的。這些差異出現在可以分配給這些類型的變量的內容上。

程序類型

TProcedureprocedural type。您可以分配到類型的變量TProcedure東西這種形式:

procedure MyProcedure; 
begin 
end; 

這是一個非面向對象的程序。您不能將實例或類方法分配給TProcedure變量。但是,您可以將static class method分配給TProcedure變量。

方法指針

TMethodmethod pointer。這表示存在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(); 

匿名方法

最後我們來anonymous methods。這些比程序類型和方法指針更爲通用。可以指定以下任何使用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; 

相比,程序類型和方法指針的匿名方法的最大好處是,它們允許variable capture。例如,考慮下面的小程序來說明:

{$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 
+12

爲什麼我知道這是你之前,我到了底部? – 2013-02-20 09:50:43

+1

@MarjanVenema可能是因爲David是極少數給出巨大解釋的基礎之一,它基本上是用於SO上的Delphi標記的一個構建塊(: – ComputerSaysNo 2013-02-20 09:53:11

+5

@ComputerSaysNo那麼謝謝你,但是我不完全同意你的意見,當你說「很少有人「,我認爲在這裏有很多積極的德爾福回答者,這些回答的答案都是很好的解釋,我不會給名字命名,但是我們這些在這裏活躍的人知道他們是誰,我們都應該鼓勵通過我們的投票,回答與解釋。 – 2013-02-20 09:58:35

6

首先是anonymous method

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

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

之間的差異,二是普通method