Namespaces
Namespace, a container for identifiers so that they don't conflict with those in other Namespaces or the global scope.
Syntax
Parameters
identifier
The name of the Namespace (including nested names specifier).
aliasname
An alternate external name for the Namespace.
Description
Namespaces are declaration fields that allow to delimit the search for the names of identifiers by the compiler. Their purpose is essentially to group the identifiers logically and to avoid name conflicts between several parts of the same project.
This type of conflict stems from the fact that only one global scope is provided by default, in which there should be no name conflict. With Namespaces, this type of problem can be more easily avoided, because defining global objects in the global scope can be avoid.
Namespaces are not allowed to contain code directly, only inside procedures declared in that Namespace. That is because a Namespace is not a scope, it is not something that is executed, it is just something that can be used to hold declarations.
Any variable declared in Namespace is implicitly static and visible throughout the entire program (Static and Shared keywords are useless). Therefore only an initializer with a constant is authorized.
This type of conflict stems from the fact that only one global scope is provided by default, in which there should be no name conflict. With Namespaces, this type of problem can be more easily avoided, because defining global objects in the global scope can be avoid.
Namespaces are not allowed to contain code directly, only inside procedures declared in that Namespace. That is because a Namespace is not a scope, it is not something that is executed, it is just something that can be used to hold declarations.
Any variable declared in Namespace is implicitly static and visible throughout the entire program (Static and Shared keywords are useless). Therefore only an initializer with a constant is authorized.
Usage
Unlike another declarative region such as a Type, a Namespace can be split into several pieces. The first piece serves as declaration, and the following ones as extensions. The syntax for a Namespace extension is exactly the same as that for the declaration part.
Identifiers declared or defined within the same Namespace must not conflict. They may have the same names, but only as part of the overloading. A Namespace therefore behaves exactly like the declaration fields of Types and the global scope.
Access to Namespace identifiers is through the resolution operator ("."), by prefixing the name of the identifier to use from the name of its Namespace. However, this prefixing is useless inside the Namespace itself, just like members inside their Type.
Namespace member procedures can be defined inside this space. They can also be set outside this space, if the resolution operator is used (prefixing from the name of its Namespace). The procedures thus defined must appear after their declarations in the Namespace.
It is possible to define a Namespace within another Namespace. However, this declaration must occur at the outermost declarative level of the Namespace that will contain the Namespace. Namespace declarations can not be put inside a procedure body or inside a Type block.
When a Namespace has a very complicated name, it may be advantageous to define an alias for that name. The alias will then have a simpler name.
Names given to Namespace aliases must not conflict with the names of other identifiers in the same Namespace, whether this is the global scope or not.
Note: The parser allows to define anonymous Namespaces (without identifier term), but this is the only similarity with the actual C++ capability: The FB compiler automatically generates multiple separate anonymous Namespaces instead of one only per module in such a case.
The FB anonymous Namespaces are almost unusable because all their declarations are inaccessible, even from the body of the module that contains them. Apart from encapsulating module constructors/destructors also inside, nothing else can be done with them.
'Using (Namespaces)' command
Identifiers declared or defined within the same Namespace must not conflict. They may have the same names, but only as part of the overloading. A Namespace therefore behaves exactly like the declaration fields of Types and the global scope.
Access to Namespace identifiers is through the resolution operator ("."), by prefixing the name of the identifier to use from the name of its Namespace. However, this prefixing is useless inside the Namespace itself, just like members inside their Type.
Namespace member procedures can be defined inside this space. They can also be set outside this space, if the resolution operator is used (prefixing from the name of its Namespace). The procedures thus defined must appear after their declarations in the Namespace.
It is possible to define a Namespace within another Namespace. However, this declaration must occur at the outermost declarative level of the Namespace that will contain the Namespace. Namespace declarations can not be put inside a procedure body or inside a Type block.
When a Namespace has a very complicated name, it may be advantageous to define an alias for that name. The alias will then have a simpler name.
Names given to Namespace aliases must not conflict with the names of other identifiers in the same Namespace, whether this is the global scope or not.
Note: The parser allows to define anonymous Namespaces (without identifier term), but this is the only similarity with the actual C++ capability: The FB compiler automatically generates multiple separate anonymous Namespaces instead of one only per module in such a case.
The FB anonymous Namespaces are almost unusable because all their declarations are inaccessible, even from the body of the module that contains them. Apart from encapsulating module constructors/destructors also inside, nothing else can be done with them.
'Using (Namespaces)' command
Using (Namespaces) allows to use a identifier from a Namespace in a simplified way, without having to specify its full name (that is, the Namespace name followed by the "." operator then the identifier name).
Each Using command allows to directly use all the identifiers of the referred Namespace.
- Syntax:
Each Using command allows to directly use all the identifiers of the referred Namespace.
- Syntax:
Using identifier [, identifier [, ...] ]
- Parameters:
identifier: The name of the Namespace to use.
- Usage:
After a Using command, it is still possible to use the full names of the identifiers from a Namespace, but this is no longer necessary. The Using commands are valid from the line where they are declared until the end of the current scope block.
If a Namespace is extended after a Using directive, the identifiers defined in the Namespace extension can be then used exactly as the identifiers defined before the using directive (that is, without the full expression of their Namespace names).
When entering Using command(s) for several Namespace names, name conflicts may occur. In this case, no error is reported from the Using command(s), but an error occurs if one of the identifiers for which there is a conflict is used (using full name of the expected identifier solves the conflict).
If a Namespace is extended after a Using directive, the identifiers defined in the Namespace extension can be then used exactly as the identifiers defined before the using directive (that is, without the full expression of their Namespace names).
When entering Using command(s) for several Namespace names, name conflicts may occur. In this case, no error is reported from the Using command(s), but an error occurs if one of the identifiers for which there is a conflict is used (using full name of the expected identifier solves the conflict).
Example
Namespace extension:
Access to Namespace members:
External definition of a function declared in a Namespace:
Definition of nested Namespace:
Access with 'Using (Namespaces)' command:
Extension of Namespace after 'Using (Namespace)' command:
Conflict between local identifiers with 'Using (Namespaces)' command:
See also
Namespace A ' Declaration of Namespace A
Dim As Integer i
End Namespace
Namespace B ' Declaration of Namespace B
Dim As Integer i
End Namespace
Namespace A ' Extension of Namespace A
Dim As Integer j
End Namespace
Dim As Integer i
End Namespace
Namespace B ' Declaration of Namespace B
Dim As Integer i
End Namespace
Namespace A ' Extension of Namespace A
Dim As Integer j
End Namespace
Dim As Integer i ' Declare i in the global scope
Namespace A
Dim As Integer i = 2 ' Declare i in Namespace A
Dim As Integer j = 3 ' Declare j in Namespace A
End Namespace
i = 1 ' Use i from global scope (.i)
A.i = 4 ' Use i from Namespace A (A.i)
Namespace A
Dim As Integer i = 2 ' Declare i in Namespace A
Dim As Integer j = 3 ' Declare j in Namespace A
End Namespace
i = 1 ' Use i from global scope (.i)
A.i = 4 ' Use i from Namespace A (A.i)
Namespace A
Declare Function f () As Integer ' Declaration of f() in Namespace A (A.f())
End Namespace
Function A.f () As Integer ' Definition of f() from Namespace A (A.f())
Return 0
End Function
Declare Function f () As Integer ' Declaration of f() in Namespace A (A.f())
End Namespace
Function A.f () As Integer ' Definition of f() from Namespace A (A.f())
Return 0
End Function
Namespace A
Dim As Integer i ' (A.i)
Namespace B
Dim As Integer j ' (A.B.j)
End Namespace
End Namespace
Dim As Integer i ' (A.i)
Namespace B
Dim As Integer j ' (A.B.j)
End Namespace
End Namespace
Namespace A
Dim As Integer i ' Declaration of A.i
Dim As Integer j ' Declaration of A.j
End Namespace
Using A ' Namespace A identifiers are also used
i = 1 ' Equivalent to A.i
j = 1 ' Equivalent to A.j
Dim As Integer i ' Declaration of A.i
Dim As Integer j ' Declaration of A.j
End Namespace
Using A ' Namespace A identifiers are also used
i = 1 ' Equivalent to A.i
j = 1 ' Equivalent to A.j
Namespace A
Dim As Integer i
End Namespace
Using A
Namespace A
Dim As Integer j
End Namespace
i = 0 ' Initialize A.i
j = 0 ' Initialize A.j
Dim As Integer i
End Namespace
Using A
Namespace A
Dim As Integer j
End Namespace
i = 0 ' Initialize A.i
j = 0 ' Initialize A.j
Namespace A
Dim As Integer i ' Declare A.i
Dim As Integer j ' Declare A.j
End Namespace
Namespace B
Dim As Integer i ' Declare B.i
Dim As Integer j ' Declare B.j
Using A ' A.i/j and B.i/j are in conflict, but no error is given
End Namespace
Dim As Integer j ' Declare also j the global scope
Using B
'i = 1 ' error: Ambiguous symbol access, explicit scope resolution required (between B.i and A.i)
B.i = 1 ' ambiguity resolution solved by using full name
j = 2 ' ambiguity (between .j, B.j, A.j) solved by compiler, by choosing override .j in the global scope
Dim As Integer i ' Declare A.i
Dim As Integer j ' Declare A.j
End Namespace
Namespace B
Dim As Integer i ' Declare B.i
Dim As Integer j ' Declare B.j
Using A ' A.i/j and B.i/j are in conflict, but no error is given
End Namespace
Dim As Integer j ' Declare also j the global scope
Using B
'i = 1 ' error: Ambiguous symbol access, explicit scope resolution required (between B.i and A.i)
B.i = 1 ' ambiguity resolution solved by using full name
j = 2 ' ambiguity (between .j, B.j, A.j) solved by compiler, by choosing override .j in the global scope
Back to Programmer's Guide