php进阶之路 -- 03 命名空间
php进阶之路 -- 03 命名空间
- 命名空间概述
- 定义命名空间
- 空间成员和子空间
- 空间成员的访问
- 空间引入
- 全局空间
一、 命名空间概述
什么是命名空间?从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。具体举个例子,文件 foo.txt 可以同时在目录/home/greg 和 /home/other 中存在,但在同一个目录中不能存在两个 foo.txt 文件。另外,在目录 /home/greg 外访问 foo.txt 文件时,我们必须将目录名以及目录分隔符放在文件名之前得到 /home/greg/foo.txt。这个原理应用到程序设计领域就是命名空间的概念。
在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题:
①用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
②为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。
二、定义命名空间
命名空间在实际开发中的作用是非常大的,那么想要使用命名空间需要通过namespace关键字:
<?php
/**
* Created by PhpStorm.
* User: liujunhang
* Date: 2018/6/18
* Time: 12:11
*/ namespace ONE; class MyClass1{ public function say(){
echo __NAMESPACE__;
}
}
$obj = new MyClass1(); namespace TWO;
class MyClass1 {
public function say(){
echo __NAMESPACE__;
}
}
$obj = new MyClass1();
上面代码中,我们在同一个文件中创建了两个相同类名的类,但是代码并没有报错,原因是因为我们开启了两个命名空间,相当于在两篇内存地址中,并不冲突。
那么在使用命名空间时有以下需要注意的点:
- 如果一个脚本定义命名空间,那么必须写在有效代码的第一行。
- 在同一个文件中,可以使用魔术常量__NAMESPACE__来查看当前的命名空间。
- 一个脚本周期内,可以定义多个命名空间,并且不同的空间可以定义相同的函数、常量和类。
不同的命名空间当中,所有的内容并不会冲突和干扰。
下面的例子中存在着一种特殊情况:
原因:变量不属于空间成员。
三、空间成员和子空间
空间成员
首先,一个命名的空间内,可以有任何的php代码。但是命名空间本身只负责三种类型:常量、函数、类。其他的都不属于空间成员。
上面代码的运行结果是:
所以说,命名空间内,除了使用空间成员(类、函数和常量)受命名空间的限制之外,其他的代码都是该怎么执行就怎么执行,跟不存在命名空间一样。
子空间
同我们计算机可以存在子目录一样,内存中也同样可以存在子空间。
例如:
目录:A/B/C ,其中C就是B的子目录,B就是A的子目录。
空间:namespace A\B\C,其中C就是B的子空间,B就是A的子空间。注意使用反斜杠\,其表示的含义是创建了一个名为C的子空间,并且A和B空间也一起创建了。
例如:
进入B空间可以如下:
思考:我们能不能够在B空间中访问其子空间C的成员呢?
上面的问题不能访问的原因:所谓的父子空间只是逻辑上的划分,实际上还是处在不同的空间当中,所以并不能直接进行访问。
那么我们如何在不同的空间中进行访问呢?
四、空间成员的访问
如何在众多的命名空间中如何访问某个空间中的某个成员。
php中提供了三种访问空间成员的方式:
非限定名称访问
限定名称访问
完全限定名称访问
非限定名称访问
所谓的非限定名称访问,就是非指定名称访问,就是在访问空间成员的时候,没有指定具体的空间的名字,到目前为止,我们前面使用的所有的访问方式都属于非限定名称访问。
那么上面这种访问方式缺点是什么呢?
例如我们之前写过的实例,当我们在某个空间中直接访问(采用非限定名称访问)另外一个空间的常量时,系统就会提示我们未找到。
那么很显然,非限定名称访问,只能访问到当前所属的空间,所谓的当前所属的空间,就是当前代码向下寻找的第一个空间,存在即访问,不存在就报错。
限定名称的访问
所谓的限定名称的访问,就是从当前名称开始访问其子空间的成员。
语法形式为:
子空间名\空间成员名
我们回到上面的问题,想要从B里访问到C中的内容。可以如下:
完全限定名称访问
所谓的完全限定名称访问,就是直接从根空间(类比根目录)开始对绝对的路径的访问!
语法形式:
\空间1\空间2\...... 其中的反斜杠代的是根路径
例如:
所以,采用完全限定名称访问的最大好处是可以在任意的空间访问其他任意空间的成员。
五、空间引入
概念:
当一个脚本包含了另外一个脚本,就出现了空间引入的问题。
例如我们下面碰到的问题:
t1.php
t2.php
此时我们的问题是,t1.php中的getName()方法调用,输出结果为什么?
是HELLO,还是WORLD?
结果为什么为HELLO,而不是WORLD呢?why?
按照我们的理解,在调用getName()方法之前我们明明就已经把t2.php引入进t1.php中,那么相当于getName调用的应该是t2里面的getName()方法。
原因:
出现这种情况是由于加载机制导致的。
因为文件的载入是发生在代码的执行阶段,而不是预编译阶段。
所以此时的getName()调用其实还是属于HELLO空间内,所以还是调用的是HELLO空间内的getName()方法。
思考:
如何访问加载进来的WORLD空间的成员?
首先,不能使用非限定名称访问,因为非限定名称访问只能访问其默认的上级空间(刚才例子中getNamef()调用访问的默认的上级空间HELLO)。
其次,也不能使用限定空间名称访问,因为限定空间名称访问只能访问当前的子空间成员。除非被引入的空间是当前空间的子空间!
而如果想要使用WORLD空间的getName方法,可以使用完全限定名称访问。
空间类的引入
所谓的空间类的引入,就是把其他的空间的类引入到当前的空间,在当前的空间直接使用这个类。
具体实现方式主要是通过use的形式来进行实现。
如下:
通过use关键字我们成功的使用了另外一个空间,但是还有一个问题,如果引入的空间中的类与本空间中的类相同,例如下面:
如果真的存在上面的情况,那么代码就会报错,那么该如何解决呢?
解决方案如下:
六、 全局空间
概念
如果不给脚本定义命名空间,那么脚本中定义的内容就属于全局空间。
例如:
按照我们之前的逻辑如果想要使用这个文件,需要引入这个文件 ,如下:
我们可以尝试下面的解决方案:
php进阶之路 -- 03 命名空间的更多相关文章
- 处女作《Web全栈开发进阶之路》出版了!
书中源码下载地址:https://github.com/qinggee/WebAdvanced 01. 当初决定写博客的原因非常的纯洁:只要每个月写上 4 篇以上博客,月底的绩效奖金就多 500 块. ...
- GO语言的进阶之路-初探GO语言
GO语言的进阶之路-初探GO语言 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.为什么我们需要一门新语言 Go语言官方自称,之所以开发Go 语言,是因为“近10年来开发程序之难 ...
- GO语言的进阶之路-协程和Channel
GO语言的进阶之路-协程和Channel 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 看过我之前几篇博客小伙伴可能对Golang语言的语法上了解的差不多了,但是,如果想要你的代码 ...
- GO语言的进阶之路-面向对象编程
GO语言的进阶之路-面向对象编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 当你看完这篇文章之时,我可以说你的Golang算是入门了,何为入门?就是你去看Docker 源码能看 ...
- JavaScript进阶之路(一)初学者的开始
一:写在前面的问题和话 一个javascript初学者的进阶之路! 背景:3年后端(ASP.NET)工作经验,javascript水平一般般,前端水平一般般.学习资料:犀牛书. 如有误导,或者错误的地 ...
- OpenCV进阶之路:神经网络识别车牌字符
1. 关于OpenCV进阶之路 前段时间写过一些关于OpenCV基础知识方面的系列文章,主要内容是面向OpenCV初学者,介绍OpenCV中一些常用的函数的接口和调用方法,相关的内容在OpenCV的手 ...
- MVC进阶之路:依赖注入(Di)和Ninject
MVC进阶之路:依赖注入(Di)和Ninject 0X1 什么是依赖注入 依赖注入(Dependency Injection),是这样一个过程:某客户类只依赖于服务类的一个接口,而不依赖于具体服务类, ...
- 【SSH进阶之路】Hibernate映射——多对一单向关联映射(四)
[SSH进阶之路]Hibernate基本原理(一) ,小编介绍了Hibernate的基本原理以及它的核心,採用对象化的思维操作关系型数据库. [SSH进阶之路]Hibernate搭建开发环境+简单实例 ...
- 【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)
文件夹 [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器開始(八) [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入 ...
随机推荐
- 部署nginx脚本
cd nginx-1.12.2useradd -s /sbin/nologin nginx./configuremakemake installyum -y install mariadb maria ...
- 第二章 Vue快速入门--10-11 跑马灯效果制作
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- java面试题(目录版)
在https://www.cnblogs.com/marsitman/p/9539369.html 根据自己以往的面试经验,在该基础上做了补充和删减,均链接到相应的地址(链接失效请留言评论). 一. ...
- 放大镜如何用js
例如: let imgs = { small: ["imgA_1.jpg", "imgB_1.jpg", "imgC_1.jpg"], mi ...
- shell通配符
wildcard 通配服 匹配.c文件 *.sh----常看当前目录下sh文件 *.c----常看当前目录下c文件 []---表示中括号 e.g [0,1,2,3,4]----能匹配0,1,2,3 ...
- TCP/IP 三次握手和四次挥手
TCP 三次握手 作用:建立TCP连接 1.三次握手是客户端先发起请求到服务器,此时服务器处于LISTEN监听状态,A会先发送一个连接请求的报文---SYN=1,ACK=0,seq=x ,这个包也称为 ...
- noip训练 2018.10.22~2018.10.23
day1 100+100+0=200 T1 稍微比划一下,发现其实就是缩点双,然后区间最小值的和 T2 发现答案为原lis|+1|-1 对每个点做从前最长上升序列以及从后最长下降序列, 想了半个小时怎 ...
- 题解 【NOIP2013】转圈游戏
[NOIP2013]转圈游戏 Description n个小伙伴(编号从0到n-1)围坐一圈玩游戏.按照顺时针方向给n个位置编号,从0到n-1.最初,第0号小伙伴在第0号位置,第1号小伙伴在第1号位置 ...
- 网络编程-UDP echo server
1. UDP简介 UDP 和TCP 的区别包括 1. 面向字节流和面向报文 2. TCP必须要建立连接后才能进行数据交换,但是UDP则并没有连接的建立和释放过程.面向字节流说明,tcp报文段(segm ...
- MessagePack Java Jackson 在不关闭输出流(output stream)的情况下序列化多变量
com.fasterxml.jackson.databind.ObjectMapper 在默认的情况下在写出输入后将会关闭输出流(output stream). 如果你希望序列化多值变量在同一个输出流 ...