博客列表 >分级命名空间与trait类学习

分级命名空间与trait类学习

小星的博客
小星的博客原创
2019年11月24日 19:42:52783浏览

1. 分级命名空间

php 中命名空间是可以定义成类似目录路径的形式,如( Mi\You\Him )

当我们在一个命名空间下需要访问另一空间下的成员时,比如说类,便需要在 类前加上对应的命名空间,这就会形成比较繁琐的代码书写。

因此,可以使用 use 关键字来简化类名。

先声明几个名空间:space.php

<?php
namespace day1010\One;

class Test1
{
    public static function demo()
    {
        return __METHOD__;
    }
}

namespace day1010\One\Two;

class Test1
{
    public static function demo()
    {
        return __METHOD__;
    }
}

使用 use 来引用需要的类:

<?php

namespace day1010;

include __DIR__.'/spaces.php';

// use
// 默认从全局开始, 可以省略掉: \
// as 给当前的空间名称起一个别名
// 防止当前空间名称命名冲突

use day1010\One\Test1; // // 如果省略as ,那么当前类的别名就是当前类的去掉空间名称的类名
use day1010\One\Two\Test1 as T;

echo Test1::demo(); // day1010\One\Test1::demo
echo '<hr>';
echo T::demo(); // day1010\One\Two\Test1::demo
echo '<hr>';
echo namespace\One\Test1::demo();

PS:  namespace 关键字 和 __NAMESPACE__常量区别

1. 常量__NAMESPACE__的值是包含当前命名空间名称的字符串,这个应该很好理解。

2. 关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素。它等价于类中的 self 操作符。

    可以将 namespace看成是当前命名空间的一个引用,在使用一个类时,我们可以这样写。 

2. trait

php 只能实现单继承,无法同时从两个基类中继承属性和方法,为了解决这个问题,php实现了一种代码复用的方法,称为 trait。

trait 可以实现让一个类从 多个 trait类中进行继承,实现类似多继承的机制。

1.  trait是一种代码复用的手段

2.  trait 使用的是类的语法,不过它不是类,不能被实例化


<?php

namespace day1010;

use PDO;

trait DB
{
    public function connect($dsn, $username, $password)
    {
        return new PDO($dsn, $username, $password);
    }

    public function test()
    {
        return '这是 DB 中的 test()';
    }
}

// 查询父类
class Query
{
    public function get(PDO $pdo, $where = '')
    {
        $where = empty($where) ? '' : ' WHERE ' . $where;
        $sql = 'SELECT * FROM `staff`' . $where . ' LIMIT 5';
        $stmt = $pdo->prepare($sql);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function test()
    {
        return '这是 Query 中的 test()';
    }
}

// 定义一个 trait类
trait Query_user
{
    // 这里也定义一个 查询方法,不过改为默认查询 1条
    public function get(PDO $pdo, $where = '')
    {
        $where = empty($where) ? '' : ' WHERE ' . $where;
        $sql = 'SELECT * FROM `staff`' . $where . ' LIMIT 1';
        $stmt = $pdo->prepare($sql);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function test()
    {
        return '这是 Query_user 中的 test()';
    }
}

class Client extends Query
{
    当引用 不同trait时出现重名方法时,可以这样来区分 
    use DB, Query_user {
        DB::test insteadof Query_user; // 这里表示用 DB 中的 test方法代替 Query_user中的
        Query_user::test as q_test; // 可以将 Query_user 中 test 改名来进行使用
    }

    public $pdo = null;

    public function __construct($dsn, $username, $password)
    {
        // 这里就可以访问 DB 中的 connect方法
        $this->pdo = $this->connect($dsn, $username, $password);
    }

    public function select($where)
    {
        // 这里是 访问的 父类中的 get(),还是 trait中的get()呢?
        return $this->get($this->pdo, $where);
    }

    // public function getClassName() {
        // return $this->test();
        // return $this->q_test();
    // }


}

$client = new Client('mysql:dbname=zmx', 'root', 'root');
// 结果显示,调用的是 trait中的方法,因此,可以得知 trait 是夹在父类与子类之间的,trait会覆盖父类方法
echo '<pre>' . print_r($client->select('staff_id >3'), true);

echo $client->q_test();

总结:

1. trait 优先级比父类高,会覆盖父类中的成员方法

2. 一个类中可以继承多个 trait


声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议