Namespaces
命名空间
use-declarations.md
commit: aa9c70bda63b3ab73b15746609831dafb96f56ff
本章译文最后维护日期:2023-05-03
命名空间是已声明的名称的逻辑分组。根据名称所指的实体类型,名称被分隔到不同的命名空间中。 名称空间允许一个名称空间中出现的名称与另一个名称空间中的相同,且不会导致冲突。
在命名空间中,名称被组织在不同的层次结构中,层次结构的每一层都有自己的命名实体集合。
程序有几个不同的命名空间,每个名称空间包含不同种类的实体。使用名称时将根据上下文来在不同的命名空间中去查找该名称的声明,名称解析一章有讲到这些。
下面是一系列命名空间及其对应实体的列表:
- 类型命名空间
- 值命名空间
- 宏命名空间
- 生存期命名空间
- 标签命名空间
如何清晰地使用不同命名空间中的同名名称的示例:
#![allow(unused)] fn main() { // Foo 在类型命名空间中引入了一个类型,在值命名空间中引入了一个构造函数 struct Foo(u32); // 宏`Foo`在宏命名空间中声明 macro_rules! Foo { () => {}; } // 参数`f` 的类型中的 `Foo` 指向类型命名空间中的 `Foo` // `'Foo` 引入一个生存期命名空间里的新的生存期 fn example<'Foo>(f: Foo) { // `Foo` 引用值命名空间里的 `Foo`构造器。 let ctor = Foo; // `Foo` 引用宏命名空间里的 `Foo`宏。 Foo!{} // `'Foo` 引入一个标签命名空间里的标签。 'Foo: loop { // `'Foo` 引用 `'Foo`生存期参数, `Foo` 引用类型命名空间中的类型。 let x: &'Foo Foo; // `'Foo` 引用了 `'Foo`标签. break 'Foo; } } }
Named entities without a namespace
无命名空间的命名实体
下面的实体有显式的名称,但是这些名称不属于任何特定的命名空间。
Fields
字段
即使结构体、枚举和联合体的字段被命名,但这些命名字段并不存在于任何显式的命名空间中。它们只能通过字段表达式访问,该表达式只检测被访问的特定类型的字段名。
Use declarations
use声明
use声明命名了导入到当前作用域中的实体,但 use
项本身不属于任何特定的命名空间。相反,它可以在多个名称空间中引入别名,这取决于所导入的程序项类型。
Sub-namespaces
子命名空间
宏的命名空间分为两个子命名空间:一个子命名空间用于[那种带感叹号(!)的宏][bang style macros],另一个子命名空间用于属性。 解析属性时,此属性所影响的作用域中的任何带感叹号(!)的宏都将被忽略。 反之,解析带感叹号(!)的宏将忽略作用域中的任何属性宏。 这样可以防止一种形式的宏遮挡另一种形式的。
例如,cfg
属性和cfg
宏是宏命名空间中具有相同名称的两个不同实体,但它们仍然可以在各自的上下文中使用。
使用 use
导入来对另一个宏进行遮蔽处理仍然是错误的,不管它们的子命名空间是什么