PHP trait特性

Published on:
Tags: php

trait是一种代码复用的方法,使开发人员能够在不同层次结构的类中服用方法,增加类的灵活性。

继承机制为类型相似的子类提供方法复用的模板,
对于类型各异,处于不用层级结构的类,可以使用trait实现代码复用机制。

使用trait复用方法#

在调用类方法的时候通常都需要实例化类,并且实例化类几乎是每个类都需要的方法,因此复用实例化方法就显得有必要。

Instances.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
namespace tp\trait;

trait Instances
{

private static $instance;

public static function getInstance()
{

echo __TRAIT__."\n";
if(is_null(self::$instance))
{
self::$instance = new static();
}
return self::$instance;
}

}

Dog.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
namespace tp\controller;

use tp\trait\Instances;

class Dog
{
use Instances;

public function eat()
{
return "Dog eat.";
}
}
Desk.php
1
2
3
4
5
6
7
8
9
10
11
12
<?php
namespace tp\controller;

use tp\trait\Instances;
class Desk
{
use Instances;
public function color()
{
return "Desk white.";
}
}
Road.php
1
2
3
4
5
6
7
8
9
10
11
12
<?php
namespace tp\controller;

use tp\trait\Instances;
class Road
{
use Instances;
public function length()
{
return "Road 1km.";
}
}

声明 trait 语句

1
use tp\trait\Instances;

和使用 trait

1
use Instances;

必须要在同一个文件里面同时存在,不能分别存在于父类和子类。

TraitC.php
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
<?php
namespace app\controller;

use tp\controller\Dog;
use tp\controller\Desk;
use tp\controller\Road;

class TraitC
{

public function callDesk()
{
return Desk::getInstance()->color();
}

public function callDog()
{
return Dog::getInstance()->eat();
}

public function callRoad()
{
return Road::getInstance()->length();
}
}

调用后依次返回:

1
2
3
4
5
6
7
8
tp\trait\Instances
Desk white.

tp\trait\Instances
Dog eat.

tp\trait\Instances
Road 1km.

trait的优先级#

从基类继承的成员会被 trait 插入的成员所覆盖。
优先顺序是来自当前类的成员覆盖了 trait 的方法,
而 trait 则覆盖了被继承的方法。

Dog.php
1
2
3
4
5
6
7
8
9
10
<?php
namespace tp\controller;

class Dog extends Animal
{
public function eat()
{
return "Dog eat.";
}
}
Animal.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
namespace tp\controller;

use tp\trait\Instances;

class Animal
{
use Instances;

private static $instance;
public static function getInstance()
{
echo __CLASS__."\n";
if(is_null(self::$instance))
{
self::$instance = new static();
}
return self::$instance;
}
}

调用Dog类的eat方法后返回:

1
2
tp\controller\Animal
Dog eat.

表明使用 Animal 类的 getInstance 方法实例化 Animal 类,最后调用 Dog 类的 eat 方法。

此处 Animal 是 Dog 的基类,但是在 Animal 类中引入了 trait ,所以 Animal 被当作当前类,
并且 Animal 没有父类,所以 Animal 类中的 getInstance 方法优先级最高,优先执行。

参考#

Trait