Method Access & Calls
Methods of a Class, Record or Interface can be accessed simply by specifying their name.
For methods of the current type (i.e. the class or record that the current code is also a part of), simply the name of the method on its own suffices to access it. To access methods on a different type (or a different instance of the same type), a Member Access Expression is used, appending an .
or :
to the expression that represents the instance, followed by the method name.
By default, accessing a method means to call it, unless the expression is preceeded by an @
Address-Of operator, or the surrounding context suggests that the address of the method is expected. More on that below.
Parameter-less methods can be called with just their name, or an optional empty set of parenthesis (()
). For methods that require parameters, these must be provided in parenthesis after the method name:
type
Foo = public class
private
method Print;
method Update(aValue: String);
public
method Test(aBar: Bar);
begin
Print;
Update(aBar.Name);
aBar.NortifyOfUpdate(self);
end;
end;
In the above example, Print
and Update
can be called directly, as methods on the current instance of the class. A Member Access Expression is used to call the NortifyOfUpdate
method on aBar
– a different object.
Using self
to Avoid Ambiguity
The self
expression can be used to explicitly access a method on the current instance, in cases where the name of the field is hidden by a different identifier in scope:
method Test(aBar: Bar);
begin
var Print := new StarryNight(5, 10);
...
self.Print;
end;
In the above example, the local Print
variable (which really should have been named lPrint
) hides the Print
method. Via the self
keyword it can still be called. In this case simply adding parenthesis, Print()
, would also have resolved the ambiguity.
Generic Parameters
Methods might be defines with generic parameters. In most cases, these can be inferred from parameters of the method call, but sometimes it might be necessary to explicitly specify them, using angle brackets between the method name and the (optional) parameter list:
var x := lStringList.Select<Integer>(s -> length(s));
The above example would compile without the explicit <Integer>
because the type can be inferred from the code in the Lambda Expression, but it is good to have the option to be explicit.
Multi-Part Method Names
Methods can have Multi-part Method Names that give a more expressive description for individual parameters. The individual parts of the method name will be used for the call in the same way as they are in the declaration, with each part being followed by a set of parenthesis containing a subset of parameters:
lObject.RunCommand('ebuild') Arguments('MyProject.sln', '--configuration:Debug');
Trailing Closures
If the last parameter of a Method (or Constructor) is a Block type used as a callback, rather than passing a method name or Anonymous Method, the block can follow the method call as a "trailing closure". This allows for a more natural integration of the callback into the flow of code and essentially makes the method call feel more like a native language construct being followed by an begin
/end
block:
The following snippet shows a call to dispatch_async
with a trailing closure:
dispatch_async(dispatch_get_main_queue) begin
// do work on the main thread
end;
If the closure receives any parameters, their names will be inferred from the declaration of the method or the Block type used in the declaration, and become available as if they were local identifiers:
remoteAdapter.beginGetDataTablewWithSQL('SELECT * FROM FOO') begin
writeLn(table)
end;
To avoid ambiguity, trailing closures are not supported inside require
/ensure
clauses of Class Contracts.
Getting the Address of a Method
Sometimes, instead of calling a method, one needs to obtain its address – typically to assign to an Event or pass it as a Block. There are two ways to achieve this.
Preceding the method access expression with the @
Address-Of operator will always return its address:
var m := @lMyObject.Foo; // get the address
...
m(); // call it, later
Alternatively the compiler will also infer that the address of the method is requested, based on the context the method access expression is used in – for example when assigning to a Block type variable/parameter or to an event via +=
/-=
:
Button.Click += OnClick;
var callback: block := OnSuccess;
Note that parenthesis after the method name are not permitted when obtaining a method's address. In fact, specifying either @
or an empty set of ()
can resolve (rare) ambiguities where both the methods address or its result would be valid (for example, if the method's return value is a block of the same type as the method itself).
See Also
- Properties
- Assign Statements
- Member Access Expressions