2013-02-20 17 views

ответ

72

Рассмотрим следующие три объявления типа:

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

Они все очень похожи друг на друга. Что касается вызова экземпляров каждого из этих трех типов, вызывающий код идентичен. Различия возникают в том, что может быть присвоено переменным этих типов.

Процедурные типы

TProcedure является procedural type. Вы можете присвоить переменной типа TProcedure что-то такой формы:

procedure MyProcedure; 
begin 
end; 

Это не объектно-ориентированная процедура. Вы не можете назначить метод экземпляра или класса переменной TProcedure. Однако вы можете назначить static class method переменной TProcedure.

Метод указателей

TMethod является method 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; 

Теперь, хотя method1 и method2 относятся к одной и той же части кода, они связаны с различными экземплярами объекта. Таким образом, если мы называем

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

Почему я знаю, что это ты, прежде чем я добрался до дна? –

+1

@MarjanVenema, вероятно, потому, что Дэвид является одним из немногих, которые дают огромное объяснение, в основном строительный блок для тега Delphi на SO (: – ComputerSaysNo

+5

@ComputerSaysNo Хорошо, спасибо, но я не совсем согласен с вами, когда вы говорите " очень немногие ». Я думаю, что здесь есть много активных ответчиков Delphi, которые отвечают с хорошими объяснениями. Я не буду называть имена, но те из нас, кто здесь активен, знают, кто они. Мы все должны стремиться –

Смежные вопросы