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
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/15109.html