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 my_integer = integer;
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 begin ShowMessage('Hi'); end; var my_proc: Procedure; // declare our alias begin my_proc := HelloWorld; // assign the alias // ... if assigned(my_proc) then // verify the reference my_proc; // call the alias 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 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); begin ShowMessage('Hello ' + name); end; function Nine: integer; begin Result := 9; end; var argumentative: procedure(s: string) = Hello; 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 TMethod = procedure of object; TFunc = function: integer of object; 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.
6 replies on “How to Reference a Procedure”
That’s not an alias. It’s a procedural variable. Different from a procedure.
With a type alias, the type and its alias are indistinguishable. That’s not the case with a procedure a procedural variable.
Jim, thank you very much for this simple tutorial! I’ve needed to do this kind of thing (with members of an object) a few times and I was never able to figure out how to do it, or if it was even possible. Now I know thanks to you!
@David Heffernan – Right you are, but is there really a way you know of to actually alias a procedure in the true sense of the term?
No I don’t think there is. I do think that terminology and detail are important. Using terminology in a sloppy and imprecise manner is not constructive, in my view.
I am on David’s side. To avoid mix in your head when you start to work with anonymous methods it is very useful to have in head right words and termins. When you have wrong ones it is very difficult to read 3rd party documentations and so on.
Also I would advice to read about generics aspect of procedural type. It is really cool and easy to use (TFunc, TPredicate and so on).
Procedure alias is not very often to meet in theoretical documentation about amonymous methods and lamdba functions. It is really better to refer it as procedural or functional (Scala is example here) type.
Added clarification.