命名空间实例详解

使用namespace关键字可以定义命名空间,定义命名空间后,其中的代码就被一个单独的空间给隔离了。

一个文件中可以有多个命名空间,其中第一个命名空间的定义语句前不能有任何代码(php标签除外)。

<?php
namespace A;                #
class 字母{                 #   此区域就是命名空间A的区域
    public $字母 = 'A';     #
}                           # 

namespace B;                #
class 字母{                 #   此区域与之后的全部区域都是命名空间B的区域
    public $字母 = 'B';     #
}                           #

# 此例中的类可以理解为正常的类,为了节约篇幅,这里仅有一个属性。

以上代码中,命名空间A中有一个字母类,命令空间B中也有一个字母类。如果在文件下方实例化字母类,是实例化的哪个字母类呢?

<?php
namespace A;
class 字母{
    public $字母 = 'A';
}
namespace B;                            #
class 字母{                             #
    public $字母 = 'B';                 #
}                                       #  此区域都是命名空间B的区域
                                        #
$obj = new 字母();                      #
printf($obj->字母);    # 结果为:B        #

那么我想要实例化命名空间A中的字母类,如何做呢?

<?php
namespace A;
class 字母{
    public $字母 = 'A';
}
namespace B;
class 字母{
    public $字母 = 'B';
}

$obj = new \A\字母();   # 与上例对比,只有这里修改了
printf($obj->字母);   # 结果为:A

在上例中,\A\字母() 是关键要素。

其实,命名空间的层级结构与linux的目录文件层级结构很相似。

第一个\是命名空间的根命名空间,我们定义的命名空间都是在根命名空间下定义的,一般都是省略掉,如果不省略的话,那么命名空间A需要这样定义:namespace \A

然后 A就是代码中定义的命令空间。

第二个\可以理解为目录的层级结构,除了第一个\,之后的\都表示层级结构。

在最后一个 \之后,就是要使用的类(本例中是类,也可以是自定义函数等)。如:

<?php
namespace A;
function 字母(){
    return 'A';
}
namespace B;
printf(\A\字母());  # 结果为:A

如果我们将开头的例子当作单独的一个文件,起名为字母.php,我们再在另一个文件(使用.php)中导入并使用:

<?php
include '字母.php';

$字母A = new \A\字母();
printf($字母A->字母());  # 结果为:A
$字母B = new \B\字母();
printf($字母B->字母());  # 结果为:B

我们会发现每次调用命名空间下的类、方法都要加上命名空间,如果使用频繁呢?如果命名空间层级很多呢?如果导入的文件将命名空间修改了,我们是不是需要一行代码一行代码去找这些使用的命名空间?

use 关键字可以将需要用到的命名空间下的类、方法提前导入。这样在实际使用中就无需写命名空间了。就是命名空间修改了,也仅需要修改 use 关键字导入的那一行即可。

<?php
include '字母.php';
use A\字母 as A字母;  # as 表示别名,这里就表示给 字母 起个别名:A字母
use B\字母;

$obj = new A字母();  # 使用别名
printf($obj->字母);  # 结果为:A
$obj = new 字母();   # 没有设置别名,直接使用类名
printf($obj->字母);  # 结果为:A