首页 > 其他 > 详细

trait

时间:2020-05-01 11:32:46      阅读:73      评论:0      收藏:0      [点我收藏+]
<?php
/**
 * Created by PhpStorm.
 * User: YANGHY
 * Date: 2020/4/29
 * Time: 10:21
 */

/**
 *  Class TestTrait
 *  Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。
 *  Trait 为了减少单继承语言的限制,在不同层次结构内独立的类中复用 method。
 *  Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。
 *  优先顺序是当前类中的方法会覆盖 trait 方法,而 trait 方法又覆盖了基类中的方法。
 *
 */
//例子1 单个trait的使用
/**trait TraitExample{
    public function add($a,$b){
        return $a + $b;
    }
    public function sub($a, $b){
        return $a - $b;
    }
}
class TestTrait
{
    use TraitExample; // 使用trait
}
$obj = new TestTrait();
echo $obj->add(10,12)."\n";
echo $obj->sub(12,2);**/
//例子2 优先级
//trait  TraitExample{
//    public function add($a,$b){
//        return $a + $b;
//    }
//    public function sub($a, $b){
//        return $a - $b;
//    }
//}
//class Count{
//    public function add($a,$b){
//        return $a + $b + 100;
//    }
//    public function sub($a, $b){
//        return $a - $b + 100;
//    }
//}
//class TestTrait extends Count
//{
//    public function add($a,$b){
//        return $a + $b + 200;
//    }
//    public function sub($a, $b){
//        return $a - $b + 200;
//    }
//    use TraitExample; // 使用trait
//}
//$obj = new TestTrait();
//echo $obj ->add(10,10)."\n"; // 220
//echo $obj ->sub(10,10); // 200
// 例子3 多个trait通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。
/*trait Ex1{
    public function say(){
        echo "hello";
    }
}
trait Ex2{
    public function reply(){
        echo "hi";
    }
}
class Test{
    use Ex1,Ex2; // 引用多个trait
}
$obj = new Test();
$obj ->say();
echo "\n";
$obj ->reply();*/
// 4.多个trait中同名函数冲突解决方法
// insteadof 明确使用哪一个
/*trait Ex1{
    public function say(){
        echo "Ex1 say hello";
    }
    public function replay(){
        echo "Ex1 reply hi";
    }
}
trait Ex2{
    public function say(){
        echo "Ex2 say hello";
    }
    public function replay(){
        echo "Ex2 reply hi";
    }
}
class Test{
    use Ex1,Ex2{
        Ex2::say insteadof Ex1; // 使用 insteadof明确使用哪个 例如使用Ex2的say
        Ex1::replay insteadof Ex2; // 使用 Ex1的replay
    } // 引用多个trait
}
$obj = new Test();
$obj ->say(); // Ex2 say hello
echo "\n";
$obj ->replay(); // Ex1 reply hi*/
// as 引入别名
/*trait Ex1{
    public function say(){
        echo "Ex1 say hello";
    }
    public function replay(){
        echo "Ex1 reply hi";
    }
}
trait Ex2{
    public function say(){
        echo "Ex2 say hello";
    }
    public function replay(){
        echo "Ex2 reply hi";
    }
}
class Test{
    use Ex1,Ex2{
        Ex1::say insteadof Ex2;
        Ex1::replay insteadof Ex2;
        Ex2::say as Esay;
        Ex2::replay as Ereplay;
    } // 引用多个trait
}
$obj = new Test();
$obj ->say(); // Ex1 say hello
echo "\n";
$obj ->replay(); // Ex1 reply hi
echo "\n";
$obj ->Esay(); // Ex2 say hello
echo "\n";
$obj ->Ereplay(); // Ex2 say hi*/
// 修改方法的访问控制权限
/*trait Control{
    public function getC(){
        echo "public";
    }
}
class Test{
    use Control{
//        getC as private; // 修改方法权限
        getC as private getByC;//原版 getC 的访问控制并没有发生变化,生成的新的getByC控制权限为private
    }
    public function getControl($className,$method){
        $reflection = new ReflectionMethod($className,$method);
        $result = Reflection::getModifierNames($reflection->getModifiers());
        print_r($result);
    }
}
//
$obj = new Test();
//  Array
//    (
//    [0] => private
//    )

$obj ->getControl(‘Test‘,‘getC‘);
$obj ->getControl(‘Test‘,‘getbyC‘);
*/

//trait组成trait
/*trait Hello{
    public function hello(){
       echo "hello";
    }
}
trait World{
    public function world(){
        echo "world";
    }
}
trait HelloWorld{
    use Hello,World;
}
class MyHelloWorld{
    use HelloWorld;
}
$obj = new MyHelloWorld();
$obj ->hello();
echo " ";
$obj ->world();*/
//trait的抽象成员 为了对使用的类强制要求,trait支持抽象方法的使用
/*trait Hello{
    public function sayHello(){
        echo "hello ".$this->getWorld();
    }
    abstract function getWorld();
}
class Test{
    use Hello;
    private $world;
    function getWorld()
    {
       return $this->world;
    }
    function setWorld($value){
        $this ->world = $value;
    }

}
$obj = new Test();
$obj ->setWorld("world!");
$obj ->sayHello();*/

// trait 可以被静态成员和静态方法定义
/*trait StaticVf{
    static $a = ‘kral‘;
    static public function say(){
        echo "今天的天气可真好!";
    }
}
class Test{
    use StaticVf;
}
echo Test::$a;
Test::say();*/
// trait Trait 定义了一个属性后,类就不能定义同样名称的属性,否则会产生 fatal error。
// 有种情况例外:属性是兼容的(同样的访问可见度、初始默认值)。 在 PHP 7.0 之前,属性是兼容的,则会有 E_STRICT 的提醒。
/*trait StaticV{
    public $a = true;
    public $b = false;
}
class Test{
    use StaticV;
    public $a = "hello"; // Fatal error 测试版本php 7.3.1
    public $b = false; //  PHP 7.0.0 后没问题,之前版本是 E_STRICT 提醒
}
$obj = new Test();*/

// 与继承不同;如果trait具有静态属性,则使用该trait的每个类都具有这些属性的独立实例。
// 继承
/*class StaticV{
    static $a;
}
class TestStaticv extends StaticV{
}
class TestStaticv2 extends StaticV{

}
TestStaticv::$a = ‘hello‘;
TestStaticv2::$a = ‘world‘;
echo TestStaticv::$a.‘ ‘.TestStaticv2::$a; // World World*/
/*trait StaticV{
    static $a;
}
class TestTrait{
    use StaticV;
}
class TestTrait2{
    use StaticV;
}
TestTrait::$a = ‘hello‘;
TestTrait2::$a = ‘world‘;
echo TestTrait::$a.‘ ‘.TestTrait2::$a; // hello world*/
// __CLASS__ 返回使用trait的类的名称,不是调用trait方法的类
/*trait MyTrait{
    public function TestTrait(){
        echo "CLASS: ".__CLASS__;
        echo "TRAIT: ".__TRAIT__;
    }
}
class BaseClass{
    use MyTrait;
}
class TestBaseClass extends BaseClass{

}
$obj = new TestBaseClass();
$obj ->TestTrait();*/
// traits与继承的另一个区别是,traits中定义的方法可以访问它们使用的类的方法和属性,包括私有类。
/*trait MyTrait{
    protected function setVar(){
        return $this ->var;
    }
}
class TraitUser{
    use MyTrait;
    private $var = ‘var‘;
    public function getVar()
    {
        return $this ->setVar($this->var);
    }
}
$obj = new TraitUser();
echo $obj->getVar();*/

// 如前所述,trait中的静态属性和方法可以使用trait直接访问。由于trait是语言辅助的c/p,
//您应该注意,trait中的静态属性将被初始化为trait属性在类声明时的值。
/*trait Base{
    protected static $a = ‘Right‘;
    public static function printed(){
        echo static::$a.PHP_EOL;
    }
    public static function setType($value){
        static::$a = $value;
    }
}
class Test{
    use Base;
}
Base::setType(‘Left‘);
class Test2{
    use Base;
}
Base::setType(‘Center‘);
Base::printed();
Test::printed();
Test2::printed();*/
// 魔术方法__call 按预期工作
// PHP5 的对象新增了一个专用方法 __call(),
// 这个方法用来监视一个对象中的其它方法。如果你试着调用一个对象中不存在或被权限控制中的方法,__call 方法将会被自动调用.
/*trait Base{
    public function __call($name, $arguments)
    {
       return count($arguments);
    }
}
class TestTrait{
    use Base;
}
$obj = new TestTrait();
echo $obj ->go(1,2,3);*/
// trait单例
/*trait Singleton{
    public static function getSingleton(){
        static $singleton = NULL;
        $class = __CLASS__;
        return $singleton?$singleton:new $class;
    }
    public function __clone() {
        trigger_error(‘Cloning ‘.__CLASS__.‘ is not allowed.‘,E_USER_ERROR);
    }

    public function __wakeup() {
        trigger_error(‘Unserializing ‘.__CLASS__.‘ is not allowed.‘,E_USER_ERROR);
    }
}
class Test{
    use Singleton;
    private function __construct()
    {
        $this ->name =‘Test‘;
    }
}
class Test2{
    use Singleton;
    private function __construct()
    {
        $this->name = ‘Test2‘;

    }
}
$test = Test::getSingleton();
var_dump($test);
//$test11 = Test::getSingleton();
//var_dump($test11);
echo $test->name;
$test2 = Test2::getSingleton();
echo $test2 ->name;
var_dump($test2);*/

 

trait

原文:https://www.cnblogs.com/kral-yang/p/12812708.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!