В чем разница между объектом и ссылкой на?

31

В чем разница между

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

и

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

Я использую объект

Теги:

2 ответа

69
Лучший ответ

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

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

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

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

TProcedure является процедурным типом. Вы можете назначить переменной типа TProcedure что-то из этой формы:

procedure MyProcedure;
begin
end;

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

Указатели методов

TMethod является указателем метода . Об этом свидетельствует наличие of object. Когда у вас есть переменная типа TMethod, вы должны назначить либо:

  • Метод экземпляра объекта-объекта, или
  • Метод класса.

Таким образом, вы можете назначить любое из них:

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();

Анонимные методы

Наконец, мы переходим к анонимным методам. Это еще более общая цель, чем процедурные типы и указатели методов. Вы можете назначить любое из следующих значений переменной, определенной с помощью синтаксиса 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
  • 12
    Почему я знал, что это ты, прежде чем я дошел до сути?
  • 1
    @MarjanVenema, вероятно, потому что Дэвид - один из немногих, кто дает огромное объяснение, в основном строительный блок для тега Delphi в SO (:
Показать ещё 3 комментария
6

Первый - анонимный метод, второй - обычный method.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню