命名空间,作用域介绍
关注 1421
命名空间
命名空间是一种标识符的管理方案,这些标识符被用于任何可能的实体,比如,变量,函数,类等。同一标识符在不同的命名空间中,其指向的目标和表示的含义是互不干扰的。
为何需要命名空间?
大型项目会用到众多的变量,函数等实体,当他们的含义接近时,采用相同的标识符将是合理的,而命名空间可以消除相同标识符之间的冲突。
嵌套命名空间
命名空间可以呈现为一种嵌套或树状结构,一个命名空间可被包含在另一个命名空间中,并具有自己的标识符。
什么是完全限定名?
在嵌套命名空间中,完全限定名是指一个标识符从根命名空间开始计算的路径,由于他是完整的,因此只要给出完全限定名,就可以定位到相关的标识符,无论当前所处的命名空间是哪一个。
什么是嵌套类型?
如果在某个类型所在的命名空间中定义另一个类型,那么被定义的类型就是嵌套类型。
在下面的 C# 代码中,枚举FlowerColor
是嵌套类型,他被定义在类Flower
中。
// 类 Flower,表示一朵花
class Flower
{
// 嵌套类型 Color
enum Color
{
// 没有颜色
None = 0,
// 红色
Red = 1,
// 白色
White = 2,
// 蓝色
Blue = 3,
}
// 字段 Color,表示花的颜色,随机产生
private Color color = (Color)new Random().Next(1, 4);
// …
}
显式命名空间
要定义显式命名空间,一般需要使用特定的关键字,并给出命名空间的完全限定名,或相对于当前命名空间的路径,名称。
在下面的 C# 代码中,我们显式定义了命名空间World.Animals
,他包含了类Lion
。
// 命名空间 World.Animals
namespace World.Animals
{
// 类 Lion,表示狮子
class Lion { }
}
隐式命名空间
隐式命名空间的定义一般由语言自动完成,通常会依据代码文件的名称和路径,或某些实体来生成。常见的一种情况是函数,每个函数都拥有自己的命名空间,因此你可以在函数内定义与函数外变量同名的变量。
模块,包
模块和包都具有命名空间的效果,他们可以用于区别功能不同的代码。一般情况下,模块是比包更小的单位,但一些语言可能会做出相反的处理。模块通常会包含变量,函数,类等实体,而包通常是多个模块的集合。在使用模块或包之前,需要进行相应的导入操作。
下面的 Node.js 模块stat
,包含了统计学校总人数的函数getPeopleCount
,以及表示学生和教师数量的变量studentCount
,teacherCount
。
// 模块 stat
// 学生的数量
exports.studentCount
// 教师的数量
exports.teacherCount
// 统计学校内的总人数
exports.getPeopleCount = function () {
return exports.studentCount + exports.teacherCount
}
在导入模块stat
后,我们使用了相关的变量和函数。
// 导入模块 stat
const stat = require('./school/stat')
// 设置学校人数
stat.studentCount = 100
stat.teacherCount = 10
// 调用模块的 getPeopleCount 函数,获取学校内的总人数
console.log(`学校内的总人数为:${stat.getPeopleCount()}`)
学校内的总人数为:110
作用域
作用域是指标识符的有效作用范围,在该范围内,标识符是可以被识别的。在命名空间系统中,一个标识符的作用域不仅限于其所在的命名空间,还包括包含在该命名空间中的命名空间。在这样的规则下,根命名空间中的标识符具有全局效果,可以被其他命名空间识别,比如,全局变量,全局函数。
当某个标识符在当前命名空间中不存在时,一般会在树状结构中逐步向根命名空间搜索,直到该标识符在某个命名空间中被找到,或以类似于“未定义”的警告结束。
下面的 C# 函数sum
会进行加法计算,计算结果被保存至函数外的total
变量。
// 变量 total,用于保存计算结果
int total = 0;
// 函数 sum,进行加法计算
void sum(int num)
{
// 函数内可以访问函数外的变量 total
total += num;
}
// 调用 sum
sum(7);
sum(9);
Console.WriteLine($"结果为:{total}");
结果为:16
源码
namespaces_and_scope.cs·codebeatme/programming·GitHub
school/stat.js·codebeatme/programming·GitHub
namespaces_and_scope.js·codebeatme/programming·GitHub