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

posted @ 2015-12-25 15:36  arvim  阅读(286)  评论(0编辑  收藏  举报