trait是一种代码复用的方法,使开发人员能够在不同层次结构的类中服用方法,增加类的灵活性。
继承机制为类型相似的子类提供方法复用的模板,
对于类型各异,处于不用层级结构的类,可以使用trait实现代码复用机制。
使用trait复用方法
在调用类方法的时候通常都需要实例化类,并且实例化类几乎是每个类都需要的方法,因此复用实例化方法就显得有必要。
Instances.php1 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.php1 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.php1 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.php1 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 语句
和使用 trait
必须要在同一个文件里面同时存在,不能分别存在于父类和子类。
TraitC.php1 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.php1 2 3 4 5 6 7 8 9 10
| <?php namespace tp\controller;
class Dog extends Animal { public function eat() { return "Dog eat."; } }
|
Animal.php1 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