PHP5.4 Trait 使用
Dec 25, 2015
今天接触了laravel框架, 发现里面使用了很多的trait, 引发了我写这博文的冲动。
Trait 是个什么鬼
PHP Trait 是一个抽象类, 不能实例化, 简单理解就是将trait的代码复制, 粘贴到你使用trait的类中. 和接口对比, 还是有区别的有这么个问题。
1
2
3
4
5
6
7
8
class DbReader extends Mysqli
{
}
class FileReader extends SplFileObject
{
}DbReader, FileReader 都需要些公共方法, 假设都设计为单列模式, 两个类都需要getInstance方法, php不支持多继承, 怎么办?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 是可以多个使用的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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中的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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冲突
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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
可以随便访问。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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