В чем разница междуВ чем разница между объектом и ссылкой?
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;
Я использую объекта
Рассмотрим следующие три объявления типа:
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
вы должны назначить либо:
Таким образом, вы можете назначить любого из них:
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
:
Например:
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
Первый anonymous method, второй обыкновенный method.
Почему я знаю, что это ты, прежде чем я добрался до дна? –
@MarjanVenema, вероятно, потому, что Дэвид является одним из немногих, которые дают огромное объяснение, в основном строительный блок для тега Delphi на SO (: – ComputerSaysNo
@ComputerSaysNo Хорошо, спасибо, но я не совсем согласен с вами, когда вы говорите " очень немногие ». Я думаю, что здесь есть много активных ответчиков Delphi, которые отвечают с хорошими объяснениями. Я не буду называть имена, но те из нас, кто здесь активен, знают, кто они. Мы все должны стремиться –