命名空间指的是程序中的具名区域。命名空间具有这样一个属性:如果事先不穿越区域名这一屏障,那么命名空间外的事物是无法访问到命名空间内的事物的。这是一个好想法,因为通过命名空间,我们可以在不同地方使用相同的名字而不会出现冲突。显然,命名空间与作用域是紧密关联的两个概念。
命名空间有助于解释清楚在一个对象顶层声明另一个对象的意义,比如:
class Manny { class Klass {}}
通过这种方式来声明Klass会使得Klass成为一个嵌套类型,并且很好地将其“隐藏”到Manny中。Manny就是个命名空间!Manny中的代码可以直接看到Klass,不过Manny外的代码则看不到。需要显式指定命名空间才能穿过命名空间所代表的屏障。要想做到这一点,必须先使用Manny的名字,后跟一个点,然后是术语Klass。简而言之,需要写成Manny.Klass。
命名空间本身并不会提供安全或隐私;只是提供了便捷的手段而已。因此,在示例1-1中,我给Manny一个Klass类,也给Moe一个Klass类。不过它们之间并不会出现冲突,因为它们位于不同的命名空间中,如果必要,我可以通过Manny.Klass与Moe.Klass来区分它们。
毫无疑问,显式使用命名空间的语法依旧是消息发送点符号语法,事实上,它们是一回事。
实际上,你可以通过消息发送进入本无法进入的作用域。Moe中的代码不能自动看到Manny中声明的Klass,不过可以采取一个额外的步骤来实现这个目标,即通过Manny.Klass。之所以可以这么做是因为它能看到Manny(因为Manny声明的层级可以被Moe中的代码看到)。