It was pointed out in the comments and on G+ that this covers type aliases, but not procedure aliases. Instead it shows how to have a variable that references a procedure and then allows you to call it by this new variable. While I used alias as meaning “reference by a different name” it does in fact have a specific definition in this context. Sorry if there was any confusion or undue frustration at imprecise terminology.
I just answered a question about how to alias a procedure. I thought it was interesting enough to share here.
It is easy enough to alias a type . . .
type<br /> my_integer = integer;<br />
then we can just use my_interger in place of integer as a type. But what about a procedure (or function for that matter)?
There are two different ways, depending on if the procedure is a member of a class. For straight up procedural procedures and functions it looks a little something like this:
procedure HelloWorld; // declare our procedure<br /> begin<br /> ShowMessage('Hi');<br /> end;</p> <p>var<br /> my_proc: Procedure; // declare our alias</p> <p>begin<br /> my_proc := HelloWorld; // assign the alias</p> <p> // ...</p> <p> if assigned(my_proc) then // verify the reference<br /> my_proc; // call the alias<br /> end;
This is pretty straight forward. We just create an
alias reference variable of the right type, and assign it to the procedure we want to alias reference. If you call an alias reference variable that is unassigned you will get a null reference access violation.
You can also streamline it a little like this
var // or as const<br /> my_proc: procedure = HelloWorld;
Then you know it is assigned. I guess this would be useful if you want to
alias reference a procedure declared in a different unit.
This works the same for functions or procedures with parameters.
procedure Hello(name: String);<br /> begin<br /> ShowMessage('Hello ' + name);<br /> end;</p> <p>function Nine: integer;<br /> begin<br /> Result := 9;<br /> end;</p> <p>var<br /> argumentative: procedure(s: string) = Hello;<br /> number: function: integer = Nine;
Notice that the name of the argument doesn’t have to match, but the number, order and types do. If they don’t then you will get the error
E2009 Incompatible types: ‘Parameter lists differ’
Now what if you are dealing with procedures or functions that are members of an object? If you try to assign them to the above types you will get the error
E2009 Incompatible types: ‘regular procedure and method pointer’
And that is because members of an object are method pointers. Fear not, you can handle them with just a slightly different type declaration:
type<br /> TMethod = procedure of object;<br /> TFunc = function: integer of object;<br /> TNotifyEvent = procedure(Sender: TObject) of object;
In this case they are declared as types with “of object” added to the end. This indicates that they are procedures of an object. AKA members or method pointers.
You can read more about procedural types and method pointers in the DocWiki.
Why would you want to do any of this? First of all, the method pointer is how the VCL & FMX handles dependency injection through event handlers. This is also really useful when combined with anonymous methods and the parallel programming library.