博客列表 >508-PHP类之命名空间

508-PHP类之命名空间

小威的博客
小威的博客原创
2018年05月09日 12:02:13718浏览
  • use 导入空间并取别名效果图:

0508.png

  • use 导入空间源代码: iphone.php


实例

<?php
//声明一个命名空间为:iphone
namespace iphone;
//导入第二个类文件
require 'mi.php';
//导入第二个命名空间  并取别名为MI7
use mi\xiaomi as MI7;

class iphoneX
{
	public $model='iphoneX';
	public $price = '8999';
	public $size = '5.5';
}

echo '手机型号:'.(new MI7)->model .' 官方售价:'.(new MI7)->price.' 屏幕尺寸:'.(new MI7)->size.' 特色功能: '. print_r((new MI7)->function,true);
echo '<hr>';
echo '手机型号:'.(new iphoneX)->model .' 官方售价:'.(new iphoneX)->price.' 屏幕尺寸:'.(new iphoneX)->size;

运行实例 »

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


  • use 导入空间源代码: mi.php


实例

<?php 

//声明命名空间为:mi
namespace mi;

	//导入第一个命名空间 并取个别名为:IPX
	use iphone\iphoneX as IPX;

class xiaomi
{
	public $model = '小米7';
	public $price = '3999';
	public $size = '5.99';
	public $function = ['曲面屏','北斗星导航','屏下指纹解锁','无线充电'];
}

运行实例 »

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



  • 知识点总结

  •  命名空间

 先理解一个重要概念:代码复用

 我们学习面向对象编程的终极目标是什么? "代码复用"

 一、彻底理解代码复用机制?

到目前为止,我们已经学到的代码复用的实现手段

 * 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.在没有使用任何命名空间的情部下,所有类,常量,函数全部声明在全局空间,用\表,现在我们在

 * 他们之前加上反斜线\之外,你会发现,执行结果也是正确的.

 *   医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院

 *   * 声明类,常量,函数的时候,前面不需要添加\,调用的时候才需要添加\ * 

 *   医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院医院

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

//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);


三、函数内访问

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.如果当前脚本声明了命名空间,则所有成员的访问,就必须使用命名空间,包括系统函数



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.用户代码:用namespace 进行标识

 * 3.用户自定义命名空间,在空间标识符后有一对花括号代码之前的分号,

 * 将属于该空间的代码全部放在花括号内

 * 4.全局空间的代码,使用一个没有标识符的namespace关键字加花括号即可,将

 * 全局代码放在这对没空间标识符的花括号内

//1. 声明一个命名空间one
namespace one {
class Demo{public $name='Peter Zhu';}
const SITE='PHP中文网';
function add($a,$b){return $a+$b;}
}
//2.声明命名空间:two
namespace two {
class Demo{public $name='朱老师';}
const  SITE = 'www.php.cn';
function add($a,$b){return $a+$b;}
}

//如果执行one空间中的代码?

//这样可以吗?貌似可以,但实际不行的

//原因是:如果当前脚本使用了命名空间,那么里面的全部代码都必须使用命名空间进行声明和访问

//echo (new \one\Demo())->name,'<br>';
//再声明一个命名空间three
namespace three{
    //如果执行one空间中的代码?
//这样可以吗?貌似可以,但实际不行的
echo (new \one\Demo())->name,'<br>';
}

//但是我的本意并不是想再生成一个命名空间,我只是想在全局空间执行一下某个空间中的代码罢了

//这就好比,你去电脑城只想买一个鼠标,结果老板说,鼠标不单买,必须买个电脑,鼠标是赠送的,这显然是不合理的。

//那么我们直接声明一个全局空间行不行?

//为什么不行呢?不是说全局空间的标识符就是反斜线\吗?

//namespace \ {
//   echo (new one\Demo())->name,'<br>'; 
//}
//以上代码是错误的

//原来默认就是全局空间,不用加反斜线的,加了就是画蛇添足,反而错了,一定要注意哟~~

namespace {  
    echo (new one\Demo())->name,'<br>';
}


  •  命名空间的分层管理

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

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

<?php
//声明命名空间one
namespace one ;
class Demo{public $name='Peter Zhu';}
const SITE='PHP中文网';
function add($a,$b){return $a+$b;}
//限定名称: 类似于相对路径访问
//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;
  • 使用别名导入命名空间

 * use 关键字的使用

<?php
//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 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议