What is the difference between
TFuncOfIntToString = reference to function(x: Integer): string;
and
TFuncOfIntToString = function(x: Integer): string of object;
I use the of object
A reference variable is a variable that points to an object of a given class, letting you access the value of an object. An object is a compound data structure that holds values that you can manipulate. A reference variable does not store its own values.
Student obj = new Student(); The objects are created in the heap area and, the reference obj just points out to the object of the Student class in the heap, i.e. it just holds the memory address of the object (in the heap).
A reference is an address that indicates where an object's variables and methods are stored. You aren't actually using objects when you assign an object to a variable or pass an object to a method as an argument. You aren't even using copies of the objects. Instead, you're using references to those objects.
So the "reference type" would be Object and the "object type" would be Integer . What makes this confusing is that there's the (standardized, official) term "reference type" that encapsulates types that can be referenced. In Java that includes all classes, enums, interfaces, arrays.
Let us consider the following three type declarations:
TProcedure = procedure; TMethod = procedure of object; TAnonMethod = reference to procedure;
These are all very similar to each other. In terms of calling instances of each of these three types, the calling code is identical. The differences arise in what can be assigned to variables of these types.
Procedural types
TProcedure
is a procedural type. You can assign to a variable of type TProcedure
something of this form:
procedure MyProcedure; begin end;
This is a non object-oriented procedure. You cannot assign an instance or class method to a TProcedure
variable. However, you can assign a static class method to a TProcedure
variable.
Method pointers
TMethod
is a method pointer. This is indicated by the presence of of object
. When you have a variable of type TMethod
you must assign either:
So you can assign either of these:
procedure TMyClass.MyMethod; begin end; class procedure TMyClass.MyClassMethod; begin end;
The big difference between a procedural type and a method pointer is that the latter contains a reference to both code and data. A method pointer is often known as a two-pointer procedural type. A variable that contains a method pointer contains references to the code and the instance/class to call it on.
Consider the following code:
var instance1, instance2: TMyClass; method1, method2: TMethod; .... method1 := instance1.MyMethod; method2 := instance2.MyMethod;
Now, although method1
and method2
refer to the same piece of code, they are associated with different object instances. So, if we call
method1(); method2();
We are invoking MyMethod
on the two distinct instances. That code is equivalent to:
instance1.MyMethod(); instance2.MyMethod();
Anonymous methods
Finally we come to anonymous methods. These are even more general purpose than procedural types and method pointers. You can assign any of the following to a variable defined using the reference to
syntax:
For example:
var AnonMethod: TAnonMethod; .... AnonMethod := MyProcedure; // item 1 above AnonMethod := instance1.MyMethod; // item 2 AnonMethod := TMyClass.MyClassMethod; // item 3
Anonymous methods, item 4 above, are those declared in-line in your code. For example:
var AnonMethod: TAnonMethod; .... AnonMethod := procedure begin DoSomething; end;
The biggest benefit of anonymous methods when compared to the procedural types and method pointers is that they allow for variable capture. For example consider the following short program to illustrate:
{$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.
This has the following output:
12 -84
The first is anonymous method, the second is ordinary method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With