Delphi XE5教程8:使用Delphi命名空间
// Project file declarations... //项目文件声明… program MyCompany.ProjectX.ProgramY; // Unit source file declaration... //单元源文件声明 unit MyCompany.ProjectX.ProgramY.MyUnit1;
内容源自Delphi XE5 UPDATE 2官方帮助《Delphi Reference》,本人水平有限,欢迎各位高人修正相关错误!
也欢迎各位加入到Delphi学习资料汉化中来,有兴趣者可QQ:34484690@qq.com
Using Namespaces with Delphi
使用Delphi命名空间
Important: RAD Studio now supports a unit scope name or prefix in addition to the namespace or unit name. In order for a name to be considered fully qualified, the unit scope name must be included. For more details, see Unit Scope Names.
重要提示:RAD Studio现在支持为命名空间或单元名称添加单元空间名称或前缀。为了让其被认为是完全合格的名称,单元空间名称必须包括在内。有关详细信息,请参见单元空间名称。
In Delphi, a unit is the basic container for types. In Delphi, a namespace is a container of Delphi units.
在Delphi中,一个单元是基本容器类型。在Delphi中,一个命名空间是Delphi单元的容器。
Unlike traditional Delphi units, namespaces can be nested to form a containment hierarchy. Nested namespaces provide a way to organize identifiers and types, and are used to disambiguate types with the same name. Since they are a container for Delphi units, namespaces may also be used to differentiate between units of the same name, that reside in different packages.
不同于传统的Delphi单元,命名空间可以嵌套,从而形成一个层次结构。嵌套的命名空间提供了一种组织标识符和类型,以及用于对具有相同名称的类型消除歧义。因为它们是Delphi单元的一个容器,命名空间也可以使用具有相同名称的单元,用其驻留在不同的包中进行区分。
For example, the class MyClass in MyNameSpace, is different from the class MyClass in YourNamespace.
例如,MyNameSpace命名空间中的MyClass,不同于YourNameSpace中的MyClass。
This topic describes the following:
本主题介绍了以下内容:
Project default namespaces, and namespace declaration.
项目的默认命名空间,以及命名空间声明。
Namespace search scope.
命名空间的搜索范围。
Using namespaces in Delphi units.
在Delphi单元中使用命名空间。
1 Declaring Namespaces
1 声明命名空间
In RAD Studio, a project file (program, library, or package) implicitly introduces its own namespace, called the project default namespace. A unit may be a member of the project default namespace, or it may explicitly declare itself to be a member of a different namespace. In either case, a unit declares its namespace membership in its unit header. For example, consider the following explicit namespace declaration:
在RAD Studio中,项目文件(程序,库或包)隐式地引入了自己的名字空间,项目调用默认的命名空间。单元在它的单元标题中声明了它是哪个命名空间的成员。例如,下面命名空间的声明:
unit MyCompany.MyWidgets.MyUnit;
First, notice that the parts of namespaces are separated by dots. Namespaces do not introduce new symbols for the identifiers between the dots; the dots are part of the unit name. The source file name for this example is MyCompany.MyWidgets.MyUnit.pas, and the compiled output file name is MyCompany.MyWidgets.MyUnit.dcu.
首先,请注意命名空间是使用.分隔各个部分。命名空间不在.之间引入新的标识符;.作为单元名称的一部分。这个例子的源文件的名称是MyCompany.MyWidgets.MyUnit.pas,并且编译输出的文件是MyCompany.MyWidgets.MyUnit.dcu。
Second, notice that the dots imply the conceptual nesting, or containment, of one namespace within another. The example above declares the unit MyUnit to be a member of the MyWidgets namespace, which itself is contained in the MyCompany namespace. Again, it should be noted that this containment is for documentation purposes only.
其次,请注意.意味着命名空间中的另一个嵌套概念,或容器。上面的例子中声明MyUnit单元是MyWidgets命名空间的一个成员,它本身是包含在MyCompany命名空间中的。再次,应该注意的是,这只是容纳文档的目的。
A project default namespace declares a namespace for all of the units in the project. Consider the following declarations:
为项目中的所有units声明一个默认的命名空间,请考虑以下声明:
Program MyCompany.Programs.MyProgram;
Library MyCompany.Libs.MyLibrary;
Package MyCompany.Packages.MyPackage;
These statements establish the project default namespace for the program, library, and package, respectively. The namespace is determined by removing the rightmost identifier (and dot) from the declaration.
这些语句为程序,库和包分别建立了默认的命名空间,命名空间从声明的最右边的标识符(以及.)确定。
A unit that omits an explicit namespace is called a generic unit. A generic unit automatically becomes a member of the project default namespace. Given the preceding program declaration, the following unit declaration would cause the compiler to treat MyUnit as a member of the MyCompany.Programs namespace.
一个没有显式声明的命名空间中的单元称为常规单元。一个常规单元自动变为项目的默认命名空间的成员。在程序前面给出声明,下列单元声明会导致编译器把MyUnit作为MyCompany.Programs命名空间的成员。
unit MyUnit;
The project default namespace does not affect the name of the Delphi source file for a generic unit. In the preceding example, the Delphi source file name would be MyUnit.pas. The same rule applies for the dcu file name. The resulting dcu file in the current example would be MyUnit.dcu.
项目的默认命名空间不影响对一个常规单元的Delphi源文件的名称。在前面的例子中,Delphi源文件的名称将是MyUnit.pas。同样的规则也适用于该DCU文件名。在当前的例子中所得到的DCU文件将MyUnit.dcu。
Namespace strings are not case-sensitive. The compiler considers two namespaces that differ only in case to be equivalent. However, the compiler does preserve the case of a namespace, and will use the preserved casing in output file names, error messages, and RTTI unit identifiers. RTTI for class and type names will include the full namespace specification.
命名空间的字符串是不区分大小写的。编译器认为两个只有大小写不同的命名空间是等价的。但是,编译器会在这种情况下保留命名空间,并且将在输出文件名,错误信息,和RTTI单元标识符中保存。RTTI的类和类型名称将包含完整命名空间。
1 Searching Namespaces
2 搜索命名空间
A unit must declare the other units on which it depends. The compiler must search these units for identifiers. For units in explicit namespaces the search scope is already known, but for generic units, the compiler must establish a namespace search scope.
单元必须声明它所依赖的其它单元。编译器必须通过标识符搜索这些单元。对于明确命名空间的单元,搜索空间是已知的,但对于常规单元,编译器必须建立一个命名空间搜索范围。
Consider the following unit and uses declarations:
考虑下面的单元并使用声明:
unit MyCompany.ProjectX.ProgramY.MyUnit1; uses MyCompany.Libs.Unit2, Unit3, Unit4;
These declarations establish MyUnit1 as a member of the MyCompany.ProjectX.ProgramY namespace. MyUnit1 depends on three other units: MyCompany.Libs.Unit2, and the generic units, Unit3, and Unit4. The compiler can resolve identifier names in Unit2, since the uses clause specified the fully qualified unit name. To resolve identifier names in Unit3 and Unit4, the compiler must establish a namespace search order.
这个声明建立MyUnit1作为MyCompany.ProjectX.ProgramY命名空间的一个成员。MyUnit1依赖于3个其它单元:MyCompany.Libs.Unit2和常规单元Unit3、Unit4。编译器可以解析Unit2,因为uses子句指定了完全限制的单元名称。要解析Unit3、Unit4的单元名称,编译器必须建立一个命名空间搜索顺序。
1.1 Namespace search order
2.1 命名空间搜索顺序
Search locations can come from three possible sources: compiler options, the project default namespace, and the current unit's namespace.
搜索位置可以来自三个可能的来源:编译器选项,项目默认的命名空间,和当前单元的命名空间。
The compiler resolves identifier names in the following order:
编译器将按以下顺序解析标识符名称:
- The current unit namespace (if any)
当前单元命名空间(如果有的话)
- The project default namespace (if any)
项目的默认命名空间(如果有的话)
- Namespaces specified by compiler options.
由编译器选项指定的命名空间。
2.2 A namespace search example
2.2 一个命名空间搜索例子
The following example project and unit files demonstrate the namespace search order:
以下示例项目和单元文件证明命名空间搜索顺序:
Given this program example, the compiler would search namespaces in the following order:
基于这个程序的例子,编译器会按如下顺序搜索命名空间:
1. MyCompany.ProjectX.ProgramY
2. MyCompany.ProjectX
3. Namespaces specified by compiler options. 由编译器选项指定的命名空间。
Note that if the current unit is generic (i.e. it does not have an explicit namespace declaration in its unit statement), then resolution begins with the project default namespace.
请注意,如果当前单元是常规的(即它没有一个明确的命名空间声明在其单元语句中),那么开始解析项目默认命名空间。
2 Using Namespaces
3 使用命名空间
Delphi's uses clause brings a module into the context of the current unit. The uses clause must either refer to a module by its fully qualified name (i.e. including the full namespace specification), or by its generic name, thereby relying on the namespace resolution mechanisms to locate the unit.
Delphi的uses子句带来一个模块到当前单元的上下文。 uses子句必须引用它的全限定名(即包括完整的命名空间规范),或由它的常规名称,从而依靠命名空间解析机制来定位单元要指定的模块。
3.1 Fully qualified unit names
3.1完全合规的单元名称
The following example demonstrates the uses clause with namespaces:
下面示例演示了使用uses子句和命名空间:
unit MyCompany.Libs.MyUnit1; uses MyCompany.Libs.Unit2, // Fully qualified name.完全合规的单元名称 UnitX; // Generic name.常规名称
Once a module has been brought into context, source code can refer to identifiers within that module either by the unqualified name, or by the fully qualified name (if necessary, to disambiguate identifiers with the same name in different units). The following Writeln statements are equivalent:
一旦模块被引入上下文,源代码根据非限定名称,或者完全合规的单元名称去识别模块内的标识符(如果有必要,要对不同单元内的相同名称去消除岐义)。下面Writeln语句是等价的:
uses MyCompany.Libs.Unit2; begin Writeln(MyCompany.Libs.Unit2.SomeString); Writeln(SomeString); end.
A fully qualified identifier must include the full namespace specification. In the preceding example, it would be an error to refer to SomeString using only a portion of the namespace:
一个完全合格的标识符必须包括完整的命名空间规范。在前面的例子中,使用命名空间中一部分去引用SomeString将会造成错误:
Writeln(Unit2.SomeString); // ERROR错误! Writeln(Libs.Unit2.SomeString); // ERROR错误! Writeln(MyCompany.Libs.Unit2.SomeString); // Correct正确. Writeln(SomeString); // Correct正确.
It is also an error to refer to only a portion of a namespace in the uses clause. There is no mechanism to import all units and symbols in a namespace. The following code does not import all units and symbols in the MyCompany namespace:
在uses子句中只使用命名空间部分也是一个错误。没有任何机制命名空间中导入所有单元和符号。下面的代码不会在MyCompany的命名空间中导入所有单元和符号:
uses MyCompany; // ERROR错误!
This restriction also applies to the with-do statement. The following will produce a compiler error:
这些限制也可以应用于with-do语句。下面过程也将产生一个编译错误:
with MyCompany.Libs do // ERROR错误!
3.2 Multi-unit Namespaces
3.2 多单元命名空间
Multiple units can belong to the same namespace, if the unit declarations refer to the same namespace. For example, one can create two files, unit1.pas and unit2.pas, with the following unit declarations:
多个units单元可以同属于相同的命名空间,如果unit单元声明引入相同的命名空间。例如,共同创建两个文件,unit1.pas 和 unit2.pas,会有以下的unit声明:
// in file 'unit1.pas' unit MyCompany.ProjectX.ProgramY.Unit1; // in file 'unit2.pas' unit MyCompany.ProjectX.ProgramY.Unit2;
In this example, the namespace MyCompany.ProjectX.ProgramY logically contains all of the interface symbols from unit1.pas and unit2.pas.
在这个例子中,命名空间MyCompany.ProjectX.ProgramY逻辑上包含所有的unit1.pas和unit2.pas接口符号。
Symbol names in a namespace must be unique, across all units in the namespace. In the example above, it is an error for Unit1 and Unit2 to both define a global interface symbol named mySymbol.
在所有命名空间中的单元的命名空间中的名称必须是唯一的。在上面的例子中,它为unit1和unit2定义一个名为mySymbol一个全局性的接口符号是错误的。
The individual units aggregated in a namespace are not available to source code unless the individual units are explicitly used in the file's uses clause. In other words, if a source file uses only the namespace, then fully qualified identifier expressions referring to a symbol in a unit in that namespace must use the namespace name, not just the name of the unit that defines that symbol.
除非文件uses子句中显式的使用独立单元,聚集在一个命名空间中的个别单位不提供源代码。换句话说,如果一个源文件使用唯一的命名空间,则完全限定标识符表达式在unit单元中引用一个符号,必须使用命名空间的名称。而不是只使用单元符号。
A uses clause may refer to a namespace as well as individual units within that namespace. In this case, a fully qualified expression referring to a symbol from a specific unit listed in the uses clause may be referred to using the actual unit name or the fully-qualified name (including namespace and unit name) for the qualifier. The two forms of reference are identical and refer to the same symbol.
Uses子句可以引用一个命名空间,以及在命名空间中的独立单元。在这种情况下,一个完全合规的标识符指的是从uses子句中列出的特定单元标识符。可以是实际使用的单元名称或完全限定名(包括命名空间和单元名称)的限定符。这两种形式的参考是相同的,并且指代相同的符号。
Note: Explicitly using a unit in the uses clause will only work when you are compiling from source or dcu files. If the namespace units are compiled into an assembly and the assembly is referenced by the project instead of the individual units, then the source code that explicitly refers to a unit in the namespace will fail.
注:显式在uses子句使用单元将只能在你要编译的源代码或DCU文件工作。如果命名空间单元被编译成一个组件和组件的项目,而不是个别单元引用,那么源代码在命名空间中显示引用一个单元将失败。