PHP之命名空间、原型与迭代

命名空间、原型、迭代

介绍

在一个大的项目中,可能会遇到同名的类,函数,常量,为了区分这些元素,我们可以将这些元素分别存放到不同的命名空间中

命名空间

知识点:
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():指针复位
上一篇:【Unity Shaders】Reflecting Your World —— Unity3D中简单的Cubemap反射


下一篇:sql