Procedures with full access to members of a
Type or
Class.
Declaration and definition
Declaring and defining member procedures.
Usage
Calling member procedures.
The hidden parameter, This
Implicit access to the instance with which non-static member procedures are called.
Access rights
Referring to other members in member procedures.
Overloading
Declaring two or more member procedures with the same name.
Static member procedures
Differences from non-static member procedures.
The term 'member procedure' refers to both static and non-static member procedures, unless otherwise noted.
Declaration and definition
Member procedures are declared much like normal module-level procedures except that they are declared within, and defined outside, a
Type or
Class definition
[1].
When defining member procedures, the procedure name is prefixed with the name of the
Type or
Class and the member access operator (
Operator . (Member Access)). It is an error to define a member procedure without a matching declaration in the
Type or
Class definition.
The following example declares and defines a
Sub and
Function member procedure:
'' foo1.bi
Type foo
Declare Sub f (As Integer)
Declare Function g As Integer
i As Integer
End Type
Sub foo.f (n As Integer)
Print n
End Sub
Function foo.g As Integer
Return 420
End Function
Usage
Member procedures are referred to just like member data, that is, their name is prefixed with the name of an object instance and the member access operator (
Operator . (Member Access))
[2].
The following example, using the code from the last example, calls
Sub and
Function member procedures:
'' ... foo with non-static members as before ...
#include once "foo1.bi"
Dim bar As foo
bar.f(bar.g())
The hidden parameter, This
Member procedures actually have an additional parameter than what they are declared with
[3]. When they are called, using the name of an instance and
Operator . (Member Access), a reference to that instance is passed along with any other arguments in the call, allowing the member procedure direct access to the instance.
The additional parameter added by the compiler is called
This, and since it's a reference, any modifications to
This are actually modifications to the instance that was passed to the member procedure when it was called. You can use
This just like any other variable, ie., pass it to procedures taking a object of the same type, call other member procedures and access member data using
Operator . (Member Access), etc.
Most of the time, however, using
This explicitly is unnecessary; member procedures can refer to other members of the instance which they are passed directly by name, without having to qualify it with
This and
Operator . (Member Access). The only times when you need to qualify member names with
This is when the member name is hidden, for example, by a parameter or local variable. In these situations, qualifying the member name is the only way to refer to these hidden member names.
Note:
To access duplicated symbols defined outside the Type use: .SomeSymbol
(or ..SomeSymbol
if inside a With..End With block).
The following example uses the
This keyword to refer to member data whose name is hidden by a parameter and local variable:
Type foo
Declare Sub f (i As Integer)
Declare Sub g ()
i As Integer = 420
End Type
Sub foo.f (i As Integer)
'' A parameter hides T.i, so it needs to be qualified to be used:
Print this.i
End Sub
Sub foo.g ()
'' A local variable hides T.i, so it needs to be qualified to be used:
Dim i As Integer
Print this.i
End Sub
Access rights
Unlike normal module-level procedures, member procedures have full access rights to the members of the
Type or
Class they are declared in; they can refer to the public, protected and private members of a
Type or
Class.
Overloading
A member procedure can be declared to have the same name as another member procedure, provided the parameters are different, either in number or in type. This is referred to as overloading.
Only the parameters are used to determine if a procedure declaration is a valid overload. For example, a
Type or
Class could have static and non-static member procedures with the same name, or
Sub and
Function member procedures with the same name
Unlike a module-level procedure, which needs to specify the
Overload clause in the declaration to allow overloading it, a member procedure is overloadable by default, and does not need the
Overload clause.
Type T
Declare Sub f
'' Different number of parameters:
Declare Sub f (As Integer)
'' Different type of parameters:
Declare Sub f (ByRef As String)
'' Again, parameters are different:
Declare Function f (As UByte) As Integer
'' following three members would cause an error,
'' number of parameters and/or types do not differ:
'' Declare Function f As Integer
'' Declare Function f (As UByte) As String
'' Declare Static Function f (As UByte) As Integer
'' ...
somedata As Any Ptr
End Type
Static member procedures
Static member procedures are declared and defined much in the same way as non-static member procedures, with the
Static keyword preceding the declaration and definition.
Member procedures defined using the
Static keyword must be declared with the
Static keyword in the
Type or
Class definition, or a compiler error will occur. Like non-static member procedures, it is an error to define a static member procedure without a matching declaration in the
Type or
Class definition.
Do not confuse this with procedure definitions that specify static storage for their variables and objects by appending the
Static keyword to the procedure header. The
Static keyword can be used in both contexts, however; static member procedures can be defined with static variable and object storage.
The following example declares two static member procedures, the first of which also has static variable and object storage. Note that the
Static keyword is optional in the member procedure definition:
'' foo2.bi
Type foo
Declare Static Sub f (As Integer)
Declare Static Function g As Integer
i As Integer
End Type
Static Sub foo.f (n As Integer) Static
Print n
End Sub
Function foo.g As Integer
Return 420
End Function
Static member procedures can be called like non-static member procedures, qualifying the name of the procedure with the name of an instance and the member access operator (
Operator . (Member Access)).
They can also be called by qualifying the procedure name with the name of the
Type or
Class they were declared in and the member access operator (
Operator . (Member Access)). In other words, an instance is not required in order to call static-member procedures.
The following example, using the code from the last example, uses both ways to call static member procedures:
'' ... foo with static members as before ...
#include once "foo2.bi"
Dim bar As foo
bar.f(foo.g())
Unlike non-static member procedures, which are declared with an extra
This parameter, static member procedures do not get passed an instance when called. Because of this, static member procedures can only refer to constants, enumerations, other static members (data or procedures), etc., without qualifying their names. Static member procedures can still refer to non-static members when qualified with an instance, for example: a parameter or local variable.
The following example refers to a non-static member from a static procedure:
Type foo
Declare Static Sub f (ByRef As foo)
i As Integer
End Type
Sub foo.f (ByRef self As foo)
'' Ok, self is an instance of foo:
Print self.i
'' would cause error
'' cannot access non-static members, no foo instance:
'' Print i
End Sub
[1]
In the future, member procedures may be able to be defined within the Type or Class definition.
[2]
Static member procedures do not require an object instance in order to be called.
[3]
Static member procedures do not have this extra parameter added by the compiler, and so cannot access the object instance from which it was called with.