命名空间、原型、迭代
介绍
在一个大的项目中,可能会遇到同名的类,函数,常量,为了区分这些元素,我们可以将这些元素分别存放到不同的命名空间中
命名空间
知识点:
1. 命名空间就是包,用来存放目录中的类、函数、常量
2. 通过namespace关键字来声明命名空间
定义命名空间
namespace China;//定义命名空间
function getinfo(){
echo '我是中国人<br>';
}
namespace USA;
function getinfo(){
echo 'I am an America<br>';
}
调用
//调用
getinfo();//I am an America
\USA\getinfo();//I am an America
\China\getinfo();//我是中国人
例题
namespace China\Beijing\shunyi;
class Student{
}
namespace USA\Washington;
class Student{
}
# 注意:用\代表公共空间
//测试
$stu1 = new Student();//相对路径
$stu2 = new \USA\Washington\Student();//绝对路径
$stu3 = new \China\Beijing\shunyi\Student();//绝对路径
var_dump($stu1,$stu2,$stu3);
//object(USA\Washington\Student)#1 (0) { } object(USA\Washington\Student)#2 (0) { } object(China\Beijing\shunyi\Student)#3 (0) { }
语法规则
1. 公共空间+命名空间+空间元素
2. 公共空间:\
3. 命名空间:\China\Beijing\shunyi
4. 空间元素:Student::$type
5. 命名空间可以是多级的,但是连接必须只有一级,多级连接会报错,就相当于中间人只能有一个
访问命名空间的三种方式
1. 非限定名称访问
2. 完全限定名称访问
3. 限定名称访问
例子
namespace China\Beijing\shunyi;
function getinfo5(){
echo '顺义<br>';
}
namespace China\Beijing;
function getinfo(){
echo '北京<br>';
}
//测试
getinfo();//非限定名称访问 北京
\China\Beijing\getinfo();//完全限定名称访问 北京
shunyi\getinfo5();//限定名称访问 顺义
命名空间的引入
1. 通过use引入命名空间
2. 引入命名空间的拼接规则:
3. 公共空间+引入空间+(去除公共部分,公共部分只能有一级)空间元素
4. 比如:有A->B和B->C,那么可以A->B->C,但是如果有A->B->C和B->C->D这样是不能访问的,因为中间有两级
例子
//通过use引入命名空间
namespace China\Beijing\zhaoyang;
function getinfo(){
echo '李白<br>';
}
namespace USB;
function getinfo(){
echo 'USB接口<br>';
}
//引入命名空间
use China\Beijing\zhaoyang;
//测试
getinfo();//USB接口
zhaoyang\getinfo();//李白
引入常量、引入类、引入函数
namespace China\Beijing\haidian;
class Student{
}
function show(){
echo '柳宗元<br>';
}
const TYPE='学生';
namespace Asia;
//引入常量
use const China\Beijing\haidian\TYPE;
//引入类
use China\Beijing\haidian\Student;
//引入函数
use function China\Beijing\haidian\show;
//一定要记着加入function关键字,不然怎么找就不知道哪里有错
//测试
$stu = new Student();
var_dump($stu);//object(China\Beijing\haidian\Student)#4 (0) { }
echo '<br>';
echo \China\Beijing\haidian\TYPE;//学生
echo '<br>';
show();
知识点:
1. 引入类:use
2. 引入函数:use function [7.0以后才支持]
3. 引入常量:use const [7.0以后才支持]
给类、函数取别名
1. 如果引入的类和函数与当前空间的类和函数名称相同,需要给引入的类和函数取别名
2. 通过as取别名
namespace China\Beijing\zz;
class Student{
}
function getinfo(){
echo '李白<br>';
}
namespace USA\dd;
class Student{
}
function getinfo(){
echo '林肯<br>';
}
//引入类取别名
use China\Beijing\zz\Student as ChinaS;
//引入函数
use function China\Beijing\zz\getinfo as info1;
//测试
$ss = new ChinaS();
getinfo();//林肯
info1();//李白
验证公共空间
1. 如果一个页面没有namespace声明空间,这个页面的元素在公共空间下
2. 公共空间用\表示
function getsinfo(){
echo '李白2<br>';
}
//\getsinfo();李白 会出错哦,具体原因不清楚
命名空间的注意事项
总结:
1. 命名空间只能存放类、函数、const常量
2. 第一个namespace前面不能有任何的代码,空白字符、header()也不行
3. 包含2文件不影响当前的命名空间
4. 如果引入的类和函数与当前的空间的类和函数的名称相同,需要给引入的类和函数取别名
trait原型
作用:trait为了减少单继承语言的限制,可以在不同层次结构内独立的复用类的方法集
使用原型
trait A{
public function getinfo1(){
echo '锄禾日当午<br>';
}
}
//使用原型
class P{
use A;//代码复用
}
//测试
$p = new P;
$p->getinfo1();//锄禾日当午
//引入多个trait
trait B{
public function getinfo2(){
echo '床前明月光<br>';
}
}
class SS{
use A,B;
}
//测试
(new SS())->getinfo1();//锄禾日当午
(new SS())->getinfo2();//床前明月光
trait和继承结合
class F{
public function getinfo(){
echo '这是F类<br>';
}
}
trait C{
public function getinfo(){
echo '这是C原型<br>';
}
}
class DD extends F{
use C;//继承了getinfo,有被A中的getinfo覆盖
}
(new DD())->getinfo();//这是C原型
两个原型使用了同一个方法名的情况
trait A{
public function getinfo(){
echo '锄禾日当午<br>';
}
}
trait B{
public function getinfo(){
echo '床前明月光<br>';
}
}
//使用原型
class C{
//方法一:替换
use A,B{//引入A和B的trait,同时解决名称冲突
// A::getinfo insteadof B;//将A中的getinfo替换掉B中的getinfo
A::getinfo insteadof B;
B::getinfo as show;
}
}
//测试
$c = new C();
$c->getinfo();//锄禾日当午
$c->show();//床前明月光
同名冲突解决方法有两个:
1. 第一:方法替换
2. 第二:方法改名
更改权限
trait D{
private function show(){
echo '锄禾日当午1<br>';
}
}
class E{
use D{
// show as public:将show方法权限设为public
show as public show2;
}
}
(new E)->show2();//锄禾日当午1
扩展(自学):
1. 多个trait可以组成一个trait
2. trait可以定义抽象成员
3. trait可以定义静态成员
4. trait可以定义属性
迭代遍历数组
知识点:
1. 复位数组指针 reset()
2. 检查指针是否合法 获取当前指针,如果不为null就是 合法的
3. 获取当前值 current()
4. 获取当前键 key()
5. 指针下移 next()
$stu = ['tom','mark','ketty','rose'];
reset($stu);//复位指针
while (key($stu)!==null){
echo key($stu).'的值为:'.current($stu),'<br>';
next($stu);
}
迭代遍历对象
# 遍历对象、获取的是对象中属性保存的数组
//定义实现迭代器接口
class Myclass implements Iterator{
//$list属性用来保存学生数组
private $list=array();
public function addstu($name){
$this->list[]=$name;
}
//实现接口中的复位方法
public function rewind()
{
reset($this->list);
}
//验证当前指针是否合法
public function valid()
{
return key($this->list)!==null;
}
//获取值
public function current()
{
return current($this->list);
}
public function next()
{
next($this->list);
}
public function key()
{
return key($this->list);
}
}
//创建班级
$stu = new Myclass();
//添加学生
$stu->addstu('张三');
$stu->addstu('李四');
$stu->addstu('王五');
$stu->addstu('赵六');
foreach ($stu as $k=>$v):
echo $k.':'.$v.'<br>';
endforeach;
总结:
1. 迭代器是PHP的内置接口,抽象方法有:
2. current():当前值
3. key():当前键
4. next():指针下移
5. rewind():指针复位
6. valid():指针复位