命名空间 (Namespaces)
- 来源: https://www.freebasic.net/wiki/wikka.php?wakka=ProPgNamespaces
- 最后更新: 2019-09-28
命名空间,一种标识符的容器,防止其与其他命名空间或全局作用域中的标识符发生冲突。
语法
Namespace identifier [ Alias "aliasname" ]
statements
End Namespace参数
identifier
命名空间的名称(包括嵌套名称限定符)。
aliasname
命名空间的替代外部名称。
描述
命名空间是声明域,允许编译器限定标识符名称的搜索范围。其主要目的是对标识符进行逻辑分组,避免同一项目不同部分之间的命名冲突。
这类冲突源于默认只提供一个全局作用域,在其中不应存在命名冲突。使用命名空间,可以更容易地避免此类问题,因为可以避免在全局作用域中定义全局对象。
命名空间不允许直接包含代码,只能包含在该命名空间内声明的过程中。这是因为命名空间不是一个作用域,它不是被执行的东西,它只是可用来保存声明的容器。
在命名空间中声明的任何变量都隐式为静态的,且在整个程序中可见(Static 和 Shared 关键字无用)。因此只允许使用常量初始化器。
用法
与 Type 等其他声明域不同,命名空间可以分成多个片段。第一个片段作为声明,后续片段作为扩展。命名空间扩展的语法与声明部分完全相同。
同一命名空间内声明或定义的标识符不得冲突。它们可以具有相同的名称,但只能作为重载的一部分。因此,命名空间的行为与 Type 的声明域和全局作用域完全相同。
通过解析运算符(".")访问命名空间标识符,方法是在要使用的标识符名称前加上其所属命名空间的名称。然而,在命名空间内部,这种前缀是不必要的,就像 Type 内部的成员一样。
命名空间成员过程可以在命名空间内部定义。也可以在命名空间外部定义,前提是使用解析运算符(以命名空间名称为前缀)。如此定义的过程必须在命名空间的声明之后出现。
可以在另一个命名空间内定义命名空间。但是,该声明必须出现在包含该命名空间的命名空间的最外层声明级别。命名空间声明不能放在过程体内或 Type 块内。
当命名空间的名称非常复杂时,为该名称定义别名可能很有优势。别名将具有更简单的名称。
命名空间别名的名称不得与同一命名空间(无论是全局作用域还是其他)中其他标识符的名称冲突。
注意:解析器允许定义匿名命名空间(没有 identifier 项),但这是与实际 C++ 功能的唯一相似之处:FB 编译器在此情况下会自动生成多个独立的匿名命名空间,而不是每个模块只生成一个。
FB 匿名命名空间几乎无法使用,因为它们的所有声明都是不可访问的,即使从包含它们的模块体中也是如此。除了在内部封装模块构造函数/析构函数之外,再无他用。
Using (Namespaces) 命令
Using (Namespaces) 允许以简化的方式使用命名空间中的标识符,而无需指定其全名(即命名空间名称后跟 "." 运算符再跟标识符名称)。
每个 Using 命令允许直接使用所引用命名空间的所有标识符。
- 语法:
Using identifier [, identifier [, ...] ]
- 参数:
identifier:要使用的命名空间的名称。
- 用法:
在 Using 命令之后,仍然可以使用命名空间中标识符的全名,但不再是必须的。Using 命令从声明所在行开始有效,直到当前作用域块结束。
如果在 Using 指令之后扩展命名空间,则在命名空间扩展中定义的标识符可以与 Using 指令之前定义的标识符完全相同地使用(即无需使用其命名空间名称的完整表达式)。
当为多个命名空间名称输入 Using 命令时,可能会发生命名冲突。在这种情况下,Using 命令不会报告错误,但如果使用了存在冲突的标识符之一,则会发生错误(使用预期标识符的全名可解决冲突)。
示例
命名空间扩展:
start GeSHi
Namespace A ' 声明命名空间 A
Dim As Integer i
End Namespace
Namespace B ' 声明命名空间 B
Dim As Integer i
End Namespace
Namespace A ' 扩展命名空间 A
Dim As Integer j
End Namespaceend GeSHi
访问命名空间成员:
start GeSHi
Dim As Integer i ' 在全局作用域声明 i
Namespace A
Dim As Integer i = 2 ' 在命名空间 A 中声明 i
Dim As Integer j = 3 ' 在命名空间 A 中声明 j
End Namespace
i = 1 ' 使用全局作用域中的 i (.i)
A.i = 4 ' 使用命名空间 A 中的 i (A.i)end GeSHi
在命名空间外部定义命名空间内声明的函数:
start GeSHi
Namespace A
Declare Function f () As Integer ' 在命名空间 A 中声明 f() (A.f())
End Namespace
Function A.f () As Integer ' 定义来自命名空间 A 的 f() (A.f())
Return 0
End Functionend GeSHi
定义嵌套命名空间:
start GeSHi
Namespace A
Dim As Integer i ' (A.i)
Namespace B
Dim As Integer j ' (A.B.j)
End Namespace
End Namespaceend GeSHi
使用 Using (Namespaces) 命令访问:
start GeSHi
Namespace A
Dim As Integer i ' 声明 A.i
Dim As Integer j ' 声明 A.j
End Namespace
Using A ' 也可使用命名空间 A 的标识符
i = 1 ' 等价于 A.i
j = 1 ' 等价于 A.jend GeSHi
在 Using (Namespace) 命令之后扩展命名空间:
start GeSHi
Namespace A
Dim As Integer i
End Namespace
Using A
Namespace A
Dim As Integer j
End Namespace
i = 0 ' 初始化 A.i
j = 0 ' 初始化 A.jend GeSHi
使用 Using (Namespaces) 命令时本地标识符冲突:
start GeSHi
Namespace A
Dim As Integer i ' 声明 A.i
Dim As Integer j ' 声明 A.j
End Namespace
Namespace B
Dim As Integer i ' 声明 B.i
Dim As Integer j ' 声明 B.j
Using A ' A.i/j 和 B.i/j 存在冲突,但不报错
End Namespace
Dim As Integer j ' 在全局作用域也声明 j
Using B
'i = 1 ' 错误:符号访问不明确,需要显式作用域解析(B.i 和 A.i 之间)
B.i = 1 ' 使用全名解决歧义
j = 2 ' 歧义(.j、B.j、A.j 之间)由编译器解决,选择全局作用域中的 .j 覆盖end GeSHi
参见
NamespaceUsing (Namespaces)Scope...End Scope
返回 目录