命名空间详解和分类

命名空间是什么

计算机科学领域中是通过名字来使用各种代码资源(变量和子程序)的,命名空间(namespace)则是组织这些资源的一组符号,例如目录树是就硬盘上文件们的命名空间。命名空间的设计目的是提供一种让一组名称与其他名称分隔开的方式。在一个命名空间中声明的类的名称与另一个命名空间中声明的相同的类的名称不冲突。

如果你还是无法获得命名空间的概念,你只要想象给你一个1T的硬盘,但硬盘中无法创建文件夹,只能添加文件,你就能体会单一命名空间的坏处了,你必须保证1T的硬盘上所有文件的命名不能重复!这样你就能从日常操作文件夹的过程中抽象出命名空间这个概念了。

命名空间分类

我把当前不同语言中对命名空间的设计分为三类:单一命名空间、独立命令空间、目录树命名空间

首先我们知道,我们的代码都是由源文件组成的,而既然作为文件,那它们就处于某个文件系统中,而现在大部分的文件系统都采用了类似目录树的结构来组织文件的命名空间。

单一命名空间

虽然代码分布在不同的文件里,但是在运行时,所有的函数和类都会被加载到内存里,此时大家都在一个篮子里,没有不同文件不同文件夹的约束,如果此时每个类或每个函数仍旧使用它本身的名字,这就叫单一命名空间。

可以想象,你要面对跟在1T硬盘里无法建文件夹同样的问题。

你可能会说,这尼玛怎么写代码,好名字就那么多,取一个就少一个,哪来那么多名字给你取,何况自己取的名字之后都可能忘记,就别说要跟人合作的话,岂不是冲突得停不下来。

但其实不少语言都是这样的,比如C,比如Object-C(还莫名其妙地在IDE里给你建一个跟文件目录树不同的新目录结构),比如5.3之前的PHP,这种情况下的一种通用处理办法是:自制命名空间。怎么个自制法?就是在起名的时候在名字前加上前缀,完美。

目录树命名空间

单一命名空间明显是反人类的,需要设计有组织的命名空间。怎么设计呢?一个简单的思路是:既然代码由源文件组成,而源文件又被目录树组织,那命名空间能否直接使用目录树呢?我觉得可以,大家也觉得可以,于是就有了目录树命名空间。

目录树命名空间就是直接使用文件名作为代码资源最小单位的名字,每个文件夹作为不同的命名空间,使用文件夹路径区分不同的命名空间。

使用目录树作为命名空间有很多好处,比如:

  1. 优雅的一致性
  2. 使用起来非常直观,哪个命名空间下有哪些东西,打开文件夹就能看到,一目了然
  3. 由于文件系统保证了同一个文件空间下不会有文件重名,所以就等价于保证了同一个命名空间下不会有类重名,等价于保证了同名类一定有不同的命名空间,于是就保证了使用时一定有办法区分同名类

虽然目录树这么好,但还是有语言不完全按照目录树来走,甚至更有完全抛弃目录树作为命名空间的奇葩设计(其实也有其合理性啦):独立命名空间。

用Java举例,Java可以划归为「类目录树命名空间」,因为有两点不同

  1. 直接把目录树作为命名空间好像不太好实现,毕竟一个是文件系统中的东西,一个是运行环境中的东西,于是Java中还需要你在代码文件里显示地注明这个文件属于哪个命名空间(包名),但它又进行强制性地检查:你的命名空间注明得必须和文件夹路径一致!我心里不禁默默嘀咕这不是多此一举吗,不过还好现在的IDE在你建立文件的时候就会自动给你添加一条正确的命名空间
  2. Java中代码资源的最小单位可以说是类了,但Java语言允许一个文件中放多个类(虽然只能一个public的),虽然这并不是建议做法

独立命令空间

独立命名空间就是自己整一套跟目录树完全独立的命名空间,通常这个命名空间是用户自定义的,也就是由用户显示且自由地注明当前代码资源属于哪个命名空间,没有任何约束,PHP5.3之后就采用了这种做法。

这种方式初看会给人带来混淆,已经有一套由目录树构成的命名空间了,你再自己定义一套毫无关系的新的的命名空间,你不嫌累吗?你分得清吗?

当然这种做法会带来不直观的缺点,但同时也有其优点,比如在PHP的使用场景中,PHP作为脚本经常夹杂在各种资源文件中,如果完全使用目录树构成的命名空间,往往会造成空间的浪费,同时让PHP的结构变得非常松散,这就很适合由程序员自己定义一套独立的命名空间了。当然有的PHP框架会强制要求命名空间跟目录结构的一致性,这就是后话了。

时间: 2024-08-28 18:45:02

命名空间详解和分类的相关文章

Struts2之命名空间详解及JSP文件上传了解

学习案例:struts配置元素详解以及简单的jsp文件上传. 一.案例分析: a)将鼠标放在struts.xml中的package标签上.Alt+/会自动提示: 1.name 2.namespace 3.extends 4.externalReferenceResolver 5.abstract 6.strict-method-invocation b)abstract属性表示该包是抽象的,不能直接使用,需要有子包继承才能使用.Struts-default既是abstract,所以我们要继承使用

C#命名空间详解namespace

 命名空间是一个域,这在个域中所有的类型名字必须是唯一的,不同的类型分组归入到层次化的命名空间, 命名空间的好处是:1.避免名字冲突,2.便于查找类型名字. 如:System.secruity.Cryptogtaphy. 下面介绍namespace 关键字的使用. namespace test { class class0 { int i; public class0() { } }} using关键字使用 ,访问一个命名空间的内容可以通过完全限定名.如:test.class0来访问.但是每次这

jquery的事件命名空间详解

jquery现在的事件API:on,off,trigger支持带命名空间的事件,当事件有了命名空间,就可以有效地管理同一事件的不同监听器,在定义组件的时候,能够避免同一元素应用到不同组件时,同一事件类型之间的影响,还能控制一些意外的事件冒泡.在实际工作中,相信大家都用的很多,但是不一定了解它的所有细节,至少我有这样的经验,经常在碰到疑惑的时候,还得重新写例子去验证它的相关作用,所以本文想把事件命名空间相关的细节都梳理出来,将来再犯迷糊的时候可以回来翻着看看以便加深对它的理解和运用. 在详细了解命

C++命名空间详解

使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突.在C++中,变量.函数和类都是大量存在的.如果没有命名空间,这些变量.函数.类的名称将都存在于全局命名空间中,会导致很多冲突.比如,如果我们在自己的程序中定义了一个函数toupper(),这将重写标准库中的toupper()函 数,这是因为这两个函数都是位于全局命名空间中的.命名冲突还会发生在一个程序中使用两个或者更多的第三方库的情况中.此时,很有可能,其中一个库中的名 称和另外一个库中的名称是相同的,这样就冲突了.这种情况会经常发生

详解五大分类方法及其优缺点,数据挖掘师必会!

分类算法是一种在专家指导下的,有监督的数据挖掘方法,其种类很多,包括: 传统方法:线性判别法.距离判别法.贝叶斯分类器: 现代方法:决策树.神经网络ANN.支持向量机SVM: 1.决策树 决策树学习是以实例为基础的归纳学习算法,它着眼于从一组无次序.无规则的实例中,推理出以决策树表示的分类规则. 2.贝叶斯 贝叶斯(Bayes)分类算法是一类利用概率统计知识进行分类的算法,如朴素贝叶斯(Naive Bayes)算法 这些算法主要利用Bayes定理,来预测一个未知类别的样本属于各个类别的可能性,选

XML和Schema命名空间详解

来源:https://blog.csdn.net/wanghuan203/article/details/9204337 XML和Schema具有无关平台,技术厂商,简单,规范统一等特点,极具开放性,所以使用极为广泛,而且使用简单,在XML和Schema和,个人认为比较不好理解的一点是其命名空间问题,在这篇博客里详细进行理解. 名称空间是W3C推荐标准提供的一种统一命名XML文档中的元素和属性的机制.使用名称空间可以明确标识和组合XML文档中来自不同标记词汇表的元素和属性,避免了名称之间的冲突.

php命名空间详解

index.php: <?php include 'demo.php'; use A\demo as test; use B\demo as test2; use C\demo; $obj = new test(); $obj = new test2(); echo B\b."<br>"; class c extends demo{ } $obj = new c(); $obj -> say(); demo:php <?php namespace A; c

socket编程的同步、异步与阻塞、非阻塞示例详解

socket编程的同步.异步与阻塞.非阻塞示例详解之一 分类: 架构设计与优化 简介图 1. 基本 Linux I/O 模型的简单矩阵 每个 I/O 模型都有自己的使用模式,它们对于特定的应用程序都有自己的优点.本节将简要对其一一进行介绍. 一.同步阻塞模式在这个模式中,用户空间的应用程序执行一个系统调用,并阻塞,直到系统调用完成为止(数据传输完成或发生错误). /* * \brief * tcp client */ #include <stdio.h> #include <stdlib

Python学习记录3-函数参数详解

参数详解 参数分类 普通参数 默认参数 关键字参数 收集参数 普通参数 定义时直接定义变量名 调用的时候直接把变量或者值放入指定位置 def 函数名 (参数1, 参数2, ....): 函数体 # 调用 函数名 (value1, value2, ....) # 调用的时候,具体值参考的是位置,按位置赋值 默认参数 形参带有默认值 调用的时候,如果没有对相应形参赋值,则使用默认值 def func_name(p1=v1, p2=v2, ....): func_block #调用1 func_nam