博客列表 >细说命名空间--2018-9-7

细说命名空间--2018-9-7

晓明的博客
晓明的博客原创
2018年09月07日 14:43:07583浏览

一.命名空间的相关定义和解释

     /*
 * 命名空间
 * 先理解一个重要概念:代码复用
 * 我们学习面向对象编程的终极目标是什么? "代码复用"
 *
 * 一、彻底理解代码复用机制?
 * **到目前为止,我们已经学到的代码复用的实现手段
 * 1. 函数: 代码复用最简单的方式;
 * 2. 类与对象:将函数与它可能用到的数据封装到一起;
 * 3. trait与接口:一种特殊的类,本质是仍是函数与数据的封装;
 * 4. 常量:因为常量具有一旦定义不可修改性,可以做到一次声明,随处调用,而值不会发生变化
 *
 * 二、彻底理解什么是全局?
 * 1.全局其它就是指当前脚本,是不能跨脚本的,更不是指整个项目
 * 2.全局与局部是一对双胞胎兄弟,他们有一个共同的亲爹:作用域,都由它管着
 *
 * 三、彻底理解php脚本中有哪些成员?
 * 1.变量:包括系统预置变量与用户自定义变量;
 * 2.常量:包括系统预置常量,用户自定义常量;
 * 3.函数:包括匿名函数/函数表达式/自执行函数;
 * 4.类与对象:包括抽象类,接口,trait;
 *
 *
 * 三、彻底理解什么是作用域?
******作用域主要是针对变量
 *****PHP中的变量有三种作用域: 函数作用域,全局作用域,超全局作用哉;
 * 1. 全局作用域: 在函数外部声明,在函数内部不能直接使用
 *    注: 函数中使用全局变量必须用global声明,或者使用超全局数组:$GLOBALS
 * 2. 函数作用域:也就是局部作用域,包括函数的参数以及函数内声明的变量,离开函数则自动清除;
 * 3. 超全局作用域: 除了在全局有效外,在函数内也可以不用声明直接使用
 *
 * 四、为什么要使用命名空间?
 * 1.类,函数,常量都是全局有效,包括在函数中也可以直接使用.
 * 2.因此,在全局中不允许有重名的类,函数和常量。
 * 3.如果想从外部导入一个函数库或类库,他们的函数名,类名极有可能与当前脚本冲突
 * 4.所以,必须要有一套对于工作在全局范围内的脚本成员,进行标识符命名冲突处理的机制。
 * 5.命名空间就是这样一套解决方案,他不仅可以让用户为全局成员起一个较短的名称,又解决了
 * 第三方资源的引入带来的重名问题。
 * 6.在没有使用任何命名空间的情部下,所有类,常量,函数全部声明在全局空间,用\表,现在我们在
 * 他们之前加上反斜线\之外,你会发现,执行结果也是正确的.
 *
 *   ******************************************************
 *   * 声明类,常量,函数的时候,前面不需要添加\,调用的时候才需要添加\ *

二.全局声明:类,常量,函数

实例

<?php

//一、全局声明:类,常量,函数

//1.声明类
class Demo{public $name='Peter Zhu';}

//2.声明常量
const SITE = 'PHP中文网';

//3.声明函数
function add($a,$b){return $a+$b;}

//二、全局访问
//1.实例化类并访问类成员
echo (new Demo())->name,'<br>'; 
//echo (new \Demo())->name,'<br>'; 

//2.访问常量
echo SITE,'<br>';
//echo \SITE,'<br>';

//3.调用函数
echo add(10,20);
//echo \add(10,20);

echo'<hr>';

//三、函数内访问
function test()
{
    //1.不用声明,可直接实例化类并访问成员
    echo (new Demo())->name,'<br>';  
//    echo (new \Demo())->name,'<br>';  
    
    //2.访问常量
    echo SITE,'<br>';
//    echo \SITE,'<br>';

    //3.调用函数
    echo add(10,20);  
//    echo \add(10,20);  
    
    //在函数内部也不能重复声明同名类,函数与常量
//    class Demo{}
//    define('SITE','www.php.cn');
//    function add($a,$b){return $a*$b;}
    
}

//全局调用
test();

//在全局不允许重复声明类,常量与函数
//    class Demo{}
//    define('SITE','www.php.cn');
//    function add($a,$b){return $a*$b;}

运行实例 »

点击 "运行实例" 按钮查看在线实例

三.命名空间的基本使用

      命名空间的声明与使用
 * 1.使用关键字:namespace
 * 2.php5.3+
 * 3.namespace 之前不能有除了declare和注释之外的任何代码,html也不行
 * 4.命名空间默认从全局开始定位,全局空间用\表示,类似于根目录
 * 5.如果当前脚本声明了命名空间,则所有成员的访问,就必须使用命名空间,包括系统函数

    

实例

<?php



//1. 声明一个命名空间
namespace one;

class Demo{public $name='Peter Zhu';}

const SITE='PHP中文网';

function add($a,$b){return $a+$b;}


//如果我想声明同名的类,常量与函数可以再声明一个命名空间

//2.一个脚本中允许有多个命名空间
//声明命名空间:two,使用\tow\进行引用
namespace two;

//现在声明类Demo,常量SITE,函数add,则不会冲突
class Demo{public $name='朱老师';}

const  SITE = 'www.php.cn';

function add($a,$b){return $a+$b;}

//相信大家看出来了,这非常像是在不同的目录下面,允许创建同名文件,原理是一样的

echo (new Demo)->name, '<br>'; //默认输出的是当前空间的内容
//查看一下当前的命名空间是什么?使用系统预置常量:__NAMESPACE__
echo '当前命名空间是: ',__NAMESPACE__,'<br>';

//也可以带上当前的命名空间来访问当前空间中的成员
//生成带有当前命名空间的类名
$className = __NAMESPACE__.'\Demo';

echo (new $className)->name,'<br>';

//可以带上完整的命名空间名称,从全局空间\开始,相当于从根目录开始
//专业术语: 完全限定名称
echo (new \two\Demo)->name, '<hr>'; 

//3.如何实现跨空间访问?
//如果我们要访问空间one中的Demo类中的属性,如何操作呢? 
//跨空间访问,与跨目录访问文件一样,一定要带上它完整的空间路径
//例如我们要访问one空间的类Demo中的成员
echo 'one空间的类成员:',(new \one\Demo)->name,'<br>';

//4.在声明了命名空间的脚本中,如何访问系统预定义方法?
//例如声明了一个单字符数组
$welcome = 'php中文网欢迎您';
\print_r($welcome); echo '<br>';
print($welcome); echo '<hr>';
//刚才我们说过,在空间中访问全局成员,必须要加\,这里没有加为什么可以?
//因为如果用户没有添加,那么会首先在本空间中寻找有没有var_dump()函数,
//如果没有找到,再到全局空间查找,所以不报错
//但是如果我们在当前的two空间中也创建一个var_dump()函数,则只会执行
//当前空间中用户自定义的var_dump(),系统同名函数不会被调用
function print_r($arg)
{
    echo '我是当前空间声明的函数调用:'.$arg;
}
print_r($welcome); echo '<br>';
//等价调用语法:
\two\print_r($welcome);

//注意: 此print_r(),与系统内置的print_r()无任何关系,仅名称相同而已
//就好比,上海有条长江路,咱们合肥也有一条长江路一样,这二条路除名称一样,再无任何关系

// 上海市宝山区长江路
// 合肥市庐阳区长江路
// 相信没有人会认为这是同一条路?

//事实上,这二个函数的完整调用语句应该是这样的:
//1.调用系统的:
\print_r($welcome);
//2.调用当前空间的:
\two\print_r($welcome);
//尽管后面名称一样,但是归属地是不同的

运行实例 »

点击 "运行实例" 按钮查看在线实例


四.非限定名称命名空间和限定命名空间,完全限制命名空间的区别

      1.非限定名称: 空间成员名称前不使用空间前缀,类似于当前目录上访问

     2.限定名称: 类似于相对路径访问

      3.完全限定名称:从全局空间开始,类似于从根目录开始

    

实例

<?php

/* 
 *  命名空间的分层管理
 * 1.非限定名称: 空间成员名称前不使用空间前缀,类似于当前目录上访问
 * 2.
 */

//声明命名空间one
namespace one ;

class Demo{public $name='Peter Zhu';}

const SITE='PHP中文网';

function add($a,$b){return $a+$b;}

//2.限定名称: 类似于相对路径访问
//tow\Demo 会自动加上当前空间前缀:one
//最终解析为: one\two\Demo
echo (new two\Demo)->name,'<br>';

//声明命名空间two,two是one的子空间
namespace one\two;

class Demo{public $name='朱老师';}

const  SITE = 'www.php.cn';

function add($a,$b){return $a+$b;}


//非限定名称:类似当前目录下访问
//在当前空间内访问不需要添加空间前缀
echo (new Demo)->name,'<br>';

//完全限定名称:从全局空间开始,类似于从根目录开始
//从当前的one\two\开始,访问另一个空间的成员,要从根开始
echo (new \one\Demo)->name;

运行实例 »

点击 "运行实例" 按钮查看在线实例


   五.namespace关键字和__NAMESPACE__常量

   PHP支持两种抽象的访问当前命名空间内部元素的方法,__NAMESPACE__ 魔术常量和namespace关键字。

常量__NAMESPACE__的值是包含当前命名空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它包含一个空的字符串。

__NAMESPACE__ 示例, 在命名空间中的代码

 

实例

<?php
namespace MyProject;

echo '"', __NAMESPACE__, '"'; // 输出 "MyProject"
?>
__NAMESPACE__ 示例,全局代码

<?php

echo '"', __NAMESPACE__, '"'; // 输出 ""
?>
常量 __NAMESPACE__ 在动态创建名称时很有用,例如:

使用__NAMESPACE__动态创建名称

<?php
namespace MyProject;

function get($classname)
{
    $a = __NAMESPACE__ . '\\' . $classname;
    return new $a;
}
?>
关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素。它等价于类中的 self 操作符。

namespace操作符,命名空间中的代码

<?php
namespace MyProject;

use blah\blah as mine; // see "Using namespaces: importing/aliasing"

blah\mine(); // calls function blah\blah\mine()
namespace\blah\mine(); // calls function MyProject\blah\mine()

namespace\func(); // calls function MyProject\func()
namespace\sub\func(); // calls function MyProject\sub\func()
namespace\cname::method(); // calls static method "method" of class MyProject\cname
$a = new namespace\sub\cname(); // instantiates object of class MyProject\sub\cname
$b = namespace\CONSTANT; // assigns value of constant MyProject\CONSTANT to $b
?>
namespace操作符, 全局代码

<?php

namespace\func(); // calls function func()
namespace\sub\func(); // calls function sub\func()
namespace\cname::method(); // calls static method "method" of class cname
$a = new namespace\sub\cname(); // instantiates object of class sub\cname
$b = namespace\CONSTANT; // assigns value of constant CONSTANT to $b
?>

运行实例 »

点击 "运行实例" 按钮查看在线实例

六.使用别名导入命名空间
 * use 关键字的使用

  

实例

<?php

/* 
 * 使用别名导入命名空间
 * use 关键字的使用
 */

//1. 声明一个命名空间one
namespace one ;

//use one\two\three\Demo;
//如果当前类也有一个同名的Demo类,怎么办?为导入的类取一个别名
use one\two\three\Demo as Demo1;

//class Demo1{public $name='Peter Zhu';}
class Demo{public $name='Peter Zhu';}

const SITE='PHP中文网';

function add($a,$b){return $a+$b;}

//在当前空间访问: one\two\three空间中类
//必须要添加很长的空间前缀
//echo (new two\three\Demo)->name;
//echo (new Demo)->name;
echo (new Demo1)->name;



//2.声明命名空间:one\two\three
namespace one\two\three; 

class Demo{public $name='朱老师';}

const  DOMAIN = 'www.php.cn';

function add($a,$b){return $a+$b;}

运行实例 »

点击 "运行实例" 按钮查看在线实例


声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议