Trait,命名空间的声明与导入总结

原创 2018-11-27 11:43:09 435
摘要:一.Trait特性    + Trait:代码复用机制    + Trait可以给当前类添加一些新的特征(功能);    + 如果一个类中要添加的新功能,不具备形成一个类,或不方便用类进行整理,使用Trait更方便    + Trait类似

一.Trait特性

    + Trait:代码复用机制
    + Trait可以给当前类添加一些新的特征(功能);
    + 如果一个类中要添加的新功能,不具备形成一个类,或不方便用类进行整理,使用Trait更方便
    + Trait类似于类中的插件,可在不修改父类的情况下,扩展当前类的功能;
    + Trait工作在父类(如果有)与当前类之间,可以重载父类同名成员;
    + 尽管类中的语法适用于声明Trati类,但Trait并非常规类,不允许直接实例化
    + trait使用use关键字将自身代码插入到当前的宿主类中;
    + 当trait类中的成员与用户类中的成员命名冲突时,可以通过替换(insteadof)别名(as)解决

    trait的优先级是高于父类,但是低于子类

    子类>trait>父类

    trait 工作在继承的上下文环境中,他是位于父类与子类之间的

    trait中命名冲突的话如下解决

//命名冲突的解决方法无非两种:替换,别名
use Func1,Func2{
    Func1::accident insteadof Func2;    //替代Func2的
    Func2::accident as Func2Acc;    //别名
}
trait Func1
{
    //驾驶
    public function drive()
    {
        return '支持无人驾驶';
    }
    //保养
    public function care()
    {
        return '我是trait中的care,记得及时充电就好了'.'<hr>';
    }
    //事故处理
    public function accident()
    {
        return '汽车会自动报警,你就安静的坐在车里等警察把';
    }

}

trait Func2
{
    //燃料能源
    public function fuel()
    {
        return '新能源汽车';
    }
    //事故处理
    public function accident()
    {
        return '只要不起火,电池就不爆炸!没事';
    }
}

class Auto
{
    public $brand;  //品牌
    public $purpose;    //用途

    //构造器
    public function __construct($brand,$purpose)
    {
        $this->brand =$brand;
        $this->purpose =$purpose;
    }

    //保养
    public function care()
    {
        return '请到授权的专业4S店保养'.'<hr>';
    }
}

//定义一个子类,工作类:Bus
class Bus extends Auto
{
    //子类Bus除了可以继承Bus中的成员,还可以导入Trait类中的方法成员
//    use Func1,Func2;

    //命名冲突的解决方法无非两种:替换,别名
    use Func1,Func2{
        Func1::accident insteadof Func2;    //替代Func2的
        Func2::accident as Func2Acc;    //别名
    }


    //定义一个care方法,这个方法在父类Auto中是存在的
    public function care()
    {
        return '我们是大自然的生产商,保养请致电当地经销商'.'<hr>';
    }

}
//实例化子类Bus
$bus = new Bus('安凯','客运');

//访问
echo $bus->brand,'<br>';
echo $bus->purpose,'<br>';

//访问trait中的方法
echo $bus->drive(),'<br>';
echo $bus->fuel(),'<br>';

//访问care方法
echo $bus->care();

//访问trait中的accident()
echo $bus->accident().'<br>';
echo $bus->Func2Acc().'<br>';

优先级顺序为[子类>trait>父类]   命名冲突的话使用 insteadof 来替代  as来改名

二.命名空间的基本知识

    + 定义命名空间:namespace 空间名称;
    + 命名空间主体:类/接口,函数,常量
    + 命名空间魔术常量:__NAMESPACE__;
    + 引用命名空间:namespace/空间;(类似与self)

    命名空间的适用对象:类/接口,函数,常量
    为什么是这三个?因为这三个的作用域是全局的,不允许重名,很容易命名冲突

    定义命名空间

namespace one;
//常量
const SITE = 'php中文网';

//函数
function hello()
{
    return '我学习我快乐';
}

//类
class House
{
    public static $area = 123;
}

    空间魔术常量__NAMESPACE__ 返回当前命名空间名称

echo '当前命名空间名称是:'.__NAMESPACE__.'<br>';    //one

    访问当前空间中的常量
    关键字 namespace :引用当前的空间

echo '站点名称:'.namespace\SITE.'<br>';

    访问函数

echo '当前空间的函数'. namespace\hello(),'<br>';

    在一个脚本声明多个命名空间,并调用其他命名空间的变量或方法    全局空间用\

namespace two;

const SITE = 1000;

const DOMAIN = 'www.php.cn';

class User
{
    public static $name = 'admin';
}

echo '<hr>';
echo '当前命名空间'.__NAMESPACE__.'<br>';
echo '站点域名'.DOMAIN.'<br>';
echo '站点名称:'.namespace\SITE.'<br>';
echo '站点名称:'.\one\SITE.'<br>';  //全局空间用\

echo User::$name.'<hr>';    //非限定名称
echo \two\User::$name.'<hr>';  //完全限定名称  绝对路径

echo '房屋面积是'.\one\House::$area.'<hr>'; //访问one空间下的House类中的静态成员 一定要从全局空间开始

三.声明多个命名空间

    + 在一个脚本中可以同时声明多个命名空间;
    + 使用大括号语法: namespace 空间名称{//空间代码}
    + 全局空间的名称为空:namespace{//全局空间代码}

    在命名空间中,访问一个函数的时候,会优先在当前空间中查找,如果没有找到,就会自动到全局的空间中查找

//声明first空间
namespace first
{
    echo __NAMESPACE__.'<br>';    //输出当前空间名
    class F            //声明一个类
    {
        public static function index()    //静态普通方法
        {
            return __METHOD__;        //输出方法名
        }
    }
    function var_dump($name)          //在命名空间内 可以声明与系统函数同名的函数  如果想使用系统函数需要加上"\"全局符号
        echo '我是:'.$name;
    }
    var_dump();        //自定义函数
    echo '<br>';
    \first\var_dump();  //等价与上面
    echo '<br>';
    $name = 'tony stack';
    \var_dump($name);    //系统函数
    echo '<hr>';

    如何声明一个全局空间      想访问全局空间的类中的静态方法 需要用"\类名::方法()"   而全局空间想访问其他空间的方法和变量,类中静态方法可以 直接 空间名\类名::方法名()

//声明second空间
namespace second
{
    echo __NAMESPACE__.'<br>';
    class S
    {
        public static function index()
        {
            return __METHOD__;
        }
    }
    //访问全局中的Q::index()
    echo \Q::index();
}
//声明全局空间
namespace
{
    echo __NAMESPACE__.'<br>';
    class Q
    {
        public static function index()
        {
            return __METHOD__;
        }
    }
    echo first\F::index().'<br>';
    echo second\S::index().'<br>';
}

全局用"\"来表示

四.如何导入命名空间

    + 非限定名称:适用当前空间成员,类似与当前路径;
    + 限定名称:与当前空间关联的空间,类似于相对路径;
    + 完全限定名称:导入外部空间,类似与绝对路径
    + 导入空间使用关键字use
    + 如果与当前类命名冲突,可以通过设置替换规则或别名解决;
    + 导入空间名称不会自动加载类文件,需要手工加载自定义加载机制;

        使用别名或引用,导入外部的完全限定名称的空间
        通常是为了导入外部的类,使用别名
        导入空间使用的是关键字use

        导入空间别名,默认就是从全局开始,不要再加\

namespace my_space;
use model\User as UserModel;     //导入空间别名,默认就是从全局开始,不要再加\    起了个别名UserModel
//use model\User as User;
//use model\User;  与上方等价

require 'public/User.php';
class User
{

}
//echo \model\User::insert();
//echo User::insert().'<br>';
echo UserModel::insert().'<br>';

//导入有空间名称的函数库,必须是php5.6+

require 'public/func.php';

use function func_lib\delete as del;

echo del();





批改老师:韦小宝批改时间:2018-11-27 13:56:33
老师总结:不错!一如既往写的很棒!很完整!也很规范!

发布手记

热门词条