对象和引用有什么区别?

时间:2013-02-20 08:37:07

标签: delphi

之间有什么区别
TFuncOfIntToString = reference to function(x: Integer): string; 

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

我使用的是对象

2 个答案:

答案 0 :(得分:79)

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

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

这些都非常相似。在调用这三种类型中的每一种的实例方面,调用代码是相同的。这些差异出现在可以分配给这些类型的变量的内容中。

程序类型

TProcedureprocedural type。您可以为此类型的TProcedure类型的变量分配:

procedure MyProcedure;
begin
end;

这是一个非面向对象的过程。您无法将实例或类方法分配给TProcedure变量。但是,您可以将static class method分配给TProcedure变量。

方法指针

TMethodmethod pointerof object的存在表明了这一点。如果您有TMethod类型的变量,则必须指定:

  1. 实例化对象的实例方法,或
  2. 一种课堂方法。
  3. 所以你可以指定其中任何一个:

    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. 匿名方法。
    5. 例如:

      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
      

答案 1 :(得分:7)

第一个是anonymous method,第二个是普通method