zoukankan      html  css  js  c++  java
  • PHP5.4 Trait 使用

    Trait 是个什么鬼

    PHP Trait 是一个抽象类, 不能实例化, 简单理解就是将trait的代码复制, 粘贴到你使用trait的类中. 和接口对比, 还是有区别的
    有这么个问题.

    <?php
    class DbReader extends Mysqli
    {
    }
    
    class FileReader extends SplFileObject
    {
    }
    

    DbReader, FileReader 都需要些公共方法, 假设都设计为单列模式, 两个类都需要getInstance方法, php不支持多继承, 怎么办?

    <?php
    interface Singleton
    {
        public static function getInstance();
    }
    
    class DbReader extends Mysqli implements Singleton
    {
        public static function getInstance(){ return "instanceOfDbReader";}
    }
    
    class FileReader extends SplFileObject implements Singleton
    {
        public static function getInstance(){ return "instanceOfFileReader";}
    }
    

    是你想要的吗? 显然是NO

    SO PHP特性 Trait

    <?php
    trait Singleton
    {
        private static $instance;
    
        public static function getInstance() {
            if (!(self::$instance instanceof self)) {
                self::$instance = new self;
            }
            return self::$instance;
        }
    }
    
    class DbReader extends ArrayObject
    {
        use Singleton;
    }
    
    class  FileReader
    {
        use Singleton;
    }
    $a = DbReader::getInstance();
    $b = FileReader::getInstance();
    var_dump($a);  //object(DbReader)
    var_dump($b);  //object(FileReader)
    

    是不是爽了!!!.

    使用多个Trait

    PHP Trait 是可以多个使用的

    <?php
    trait Hello
    {
        function sayHello() {
            echo "Hello";
        }
    }
    
    trait World
    {
        function sayWorld() {
            echo "World";
        }
    }
    
    class MyWorld
    {
        use Hello, World;
    }
    
    $world = new MyWorld();
    echo $world->sayHello() . " " . $world->sayWorld(); //Hello World
    

    是不是很方便!!!

    Trait 组装 Trait

    多个Trait可以组装成一个Trait

    <?php
    trait Hello
    {
        function sayHello() {
            echo "Hello";
        }
    }
    
    trait World
    {
        function sayWorld() {
            echo "World";
        }
    }
    trait HelloWorld
    {
        use Hello, World;
    }
    
    class MyWorld
    {
        use HelloWorld;
    }
    
    $world = new MyWorld();
    echo $world->sayHello() . " " . $world->sayWorld(); //Hello World
    

    Trait 优先级

    Trait中的方法重写继承父类的方法.  
    当前类中方法复写trait中的方法  
    
    <?php
    trait Hello
    {
        function sayHello() {
            return "Hello";
        }
    
        function sayWorld() {
            return "Trait World";
        }
    
        function sayHelloWorld() {
            echo $this->sayHello() . " " . $this->sayWorld();
        }
    
        function sayBaseWorld() {
            echo $this->sayHello() . " " . parent::sayWorld();
        }
    }
    
    class Base
    {
        function sayWorld(){
            return "Base World";
        }
    }
    
    class HelloWorld extends Base
    {
        use Hello;
        function sayWorld() {
            return "World";
        }
    }
    
    $h =  new HelloWorld();
    $h->sayHelloWorld(); // Hello World
    $h->sayBaseWorld(); // Hello Base World
    

    解决Trait冲突

    <?php
    trait Game
    {
        function play() {
            echo "Playing a game";
        }
    }
    
    trait Music
    {
        function play() {
            echo "Playing music";
        }
    }
    
    class Player
    {
        use Game, Music;
    }
    
    $player = new Player();
    $player->play(); // Fatal Error
    
    // resolve one
    class Player
    {
        use Game, Music {
            Music::play insteadof Game;
        }
    }
    
    $player = new Player();
    $player->play(); //Playing music
    
    // resolve two
    class Player
    {
        use Game, Music {
            Game::play as gamePlay;
            Music::play insteadof Game;
        }
    }
    
    $player = new Player();
    $player->play(); //Playing music
    $player->gamePlay(); //Playing a game
    

    使用PHP Reflection类 ReflectionClass::getTraits() 获取类使用的traits. ReflectionClass::getTraitNames() 获取类中trait名称 ReflectionClass::isTrait() 此类是否是trait

    其他特性

    trait中的 protected, private 可以随便访问

    <?php
    trait Message
    {
        private $message;
    
        function alert() {
            $this->define();
            echo $this->message;
        }
        abstract function define();
    }
    
    class Messenger
    {
        use Message;
        function define() {
            $this->message = "Custom Message";
        }
    }
    
    $messenger = new Messenger;
    $messenger->alert(); //Custom Message
    

    参考Shameer C's Blog

  • 相关阅读:
    Linux安装python3.6
    Django之Model操作
    Django
    html学习笔记-XML-Javascript
    html学习笔记-XML
    html学习笔记-DOM
    在IDEA中编辑struts国际化properties文件
    Java中的Serializable接口和transient关键字
    关于Kettle的事务和转换内步骤的顺序执行
    Mac、Linux下两个Emacs共享一个配置文件
  • 原文地址:https://www.cnblogs.com/luowen/p/5076123.html
Copyright © 2011-2022 走看看