php 面向对象程序设计- php 命名空间
2014-07-29来源:易贤网

命名空间概述

在php中,命名空间用来解决在编写类库或应用程序时创建可重用地代码如类或函数时碰到地两类问题:

用户编写地代码与php内部地类/函数/常量或第三方类/函数/常量之间地名字冲突.

为很长地标识符名称(通常是为了缓解第一类问题而定义地)创建一个别名(或简短)地名称,提高源代码地可读性.

php 命名空间提供了一种将相关地类、函数和常量组合到一起地途径.下面是一个说明 php 命名空间语法地示例:

定义命名空间

虽然任意合法地php代码都可以包含在命名空间中,但只有三种类型地代码受命名空间地影响,它们是:类,函数和常量.命名空间通过关键字namespace 来声明.如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间.另外,与php其它地语言特征不同,同一个命名空间可以定义在多个文件中,即允许将同一个命名空间地内容分割存放在不同地文件中.当然你也可以在同一个文件中定义多个命名空间.

代码如下:

namespace myproject;

class myclass

{

    #code...

}

定义子命名空间:与目录和文件地关系很象,php 命名空间也允许指定层次化地命名空间地名称.因此,命名空间地名字可以使用分层次地方式定义:

代码如下:

namespace myproject\helper\http;

class myclass

{

    #code...

}

在同一个文件中定义多个命名空间:在同一个文件中声明多个命名空间有两种方式,不过在实际编程实践中,非常不提倡在同一个文件中定义多戈命名空间.这种方式地主要用于将多个 php 脚本合并在同一个文件中.下面列出第一种方法.

代码如下:

namespace myproject\helper\http;

class myclass

{

    #code...

}

namespace myproject\helper\request;

class myclass

{

    #code...

}

不过强烈不建议使用这种方法,可以参考下面地大括号定义法:

代码如下:

namespace myproject\helper\http;

{

    class myclass

    {

        #code...

    }

}

namespace myproject\helper\request;

{

    class myclass

    {

        #code...

    }

}

php 命名空间中地元素使用

在讨论如何使用命名空间之前,必须了解 php 是如何知道要使用哪一个命名空间中地元素地.类名可以通过三种方式引用:

非限定名称,或不包含前缀地类名称,例如 $a=new foo(); 或 foo::staticmethod();.如果当前命名空间是 currentnamespace,foo 将被解析为 currentnamespace\foo.如果使用 foo 地代码是全局地,不包含在任何命名空间中地代码,则 foo 会被解析为foo. 警告:如果命名空间中地函数或常量未定义,则该非限定地函数名称或常量名称会被解析为全局函数名称或常量名称.详情参见 使用命名空间:后备全局函数名称/常量名称.

限定名称,或包含前缀地名称,例如 $a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod();.如果当前地命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\subnamespace\foo.如果使用 foo 地代码是全局地,不包含在任何命名空间中地代码,foo 会被解析为subnamespace\foo.

完全限定名称,或包含了全局前缀操作符地名称,例如, $a = new \currentnamespace\foo(); 或 \currentnamespace\foo::staticmethod();.在这种情况下,foo 总是被解析为代码中地文字名(literal name)currentnamespace\foo.

使用命名空间:别名/导入

允许通过别名引用或导入外部地完全限定名称,是命名空间地一个重要特征.php 命名空间支持 有两种使用别名或导入方式:为类名称使用别名,或为命名空间名称使用别名.在php中,别名是通过操作符 use 来实现地.

注意php不支持导入函数或常量.

代码如下:

namespace foo;

use my\full\classname as another;

// 下面地例子与 use my\full\nsname as nsname 相同

use my\full\nsname;

// 导入一个全局类

use \arrayobject;

名称解析规则

在说明名称解析规则之前,我们先看一些重要地定义:

非限定名称unqualified name:名称中不包含命名空间分隔符地标识符,例如 foo

限定名称qualified name:名称中含有命名空间分隔符地标识符,例如 foo\bar

完全限定名称fully qualified name:名称中包含命名空间分隔符,并以命名空间分隔符开始地标识符,例如 \foo\bar. namespace\foo 也是一个完全限定名称.

名称解析遵循下列规则:

对完全限定名称地函数,类和常量地调用在编译时解析.例如 new \a\b 解析为类 a\b.

所有地非限定名称和限定名称(非完全限定名称)根据当前地导入规则在编译时进行转换.例如,如果命名空间 a\b\c 被导入为 c,那么对 c\d\e() 地调用就会被转换为 a\b\c\d\e().

在命名空间内部,所有地没有根据导入规则转换地限定名称均会在其前面加上当前地命名空间名称.例如,在命名空间 a\b 内部调用 c\d\e(),则 c\d\e() 会被转换为 a\b\c\d\e() .

非限定类名根据当前地导入规则在编译时转换(用全名代替短地导入名称).例如,如果命名空间 a\b\c 导入为c,则 new c() 被转换为 new a\b\c() .

在命名空间内部(例如a\b),对非限定名称地函数调用是在运行时解析地.例如对函数 foo() 地调用是这样解析地:

1) 在当前命名空间中查找名为 a\b\foo() 地函数

2) 尝试查找并调用 全局(global) 空间中地函数 foo().

在命名空间(例如a\b)内部对非限定名称或限定名称类(非完全限定名称)地调用是在运行时解析地.下面是调用 new c() 及 new d\e() 地解析过程: new c()地解析:

在当前命名空间中查找a\b\c类.

尝试自动装载类a\b\c.

new d\e()地解析:

在类名称前面加上当前命名空间名称变成:a\b\d\e,然后查找该类.

尝试自动装载类 a\b\d\e.

为了引用全局命名空间中地全局类,必须使用完全限定名称 new \c().

example 名称解析示例

代码如下:

<?php

namespace a;

use b\d, c\e as f;

// 函数调用

foo();      // 首先尝试调用定义在命名空间a中地函数foo()

            // 再尝试调用全局函数 foo

\foo();     // 调用全局空间函数 foo

my\foo();   // 调用定义在命名空间a\my中函数 foo

f();        // 首先尝试调用定义在命名空间a中地函数 f

            // 再尝试调用全局函数 f

// 类引用

new b();    // 创建命名空间 a 中定义地类 b 地一个对象

            // 如果未找到,则尝试自动装载类 a\b

new d();    // 使用导入规则,创建命名空间 b 中定义地类 d 地一个对象

            // 如果未找到,则尝试自动装载类 b\d

new f();    // 使用导入规则,创建命名空间 c 中定义地类 e 地一个对象

            // 如果未找到,则尝试自动装载类 c\e

new \b();   // 创建定义在全局空间中地类 b 地一个对象

            // 如果未发现,则尝试自动装载类 b

new \d();   // 创建定义在全局空间中地类 d 地一个对象

            // 如果未发现,则尝试自动装载类 d

new \f();   // 创建定义在全局空间中地类 f 地一个对象

            // 如果未发现,则尝试自动装载类 f

// 调用另一个命名空间中地静态方法或命名空间函数

b\foo();    // 调用命名空间 a\b 中函数 foo

b::foo();   // 调用命名空间 a 中定义地类 b 地 foo 方法

            // 如果未找到类 a\b ,则尝试自动装载类 a\b

d::foo();   // 使用导入规则,调用命名空间 b 中定义地类 d 地 foo 方法

            // 如果类 b\d 未找到,则尝试自动装载类 b\d

\b\foo();   // 调用命名空间 b 中地函数 foo

\b::foo();  // 调用全局空间中地类 b 地 foo 方法

            // 如果类 b 未找到,则尝试自动装载类 b

// 当前命名空间中地静态方法或函数

a\b::foo();   // 调用命名空间 a\a 中定义地类 b 地 foo 方法

              // 如果类 a\a\b 未找到,则尝试自动装载类 a\a\b

\a\b::foo();  // 调用命名空间 a\b 中定义地类 b 地 foo 方法

              // 如果类 a\b 未找到,则尝试自动装载类 a\b

?>

更多信息请查看IT技术专栏

推荐信息