自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。
- Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。
- Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。
<?php//日志类class Logger{ ???//读取日志信息 ???public function log(string $message, int $level) ???{ ???????echo "[message]:{$message}" . PHP_EOL; ???????echo "[level]:{$level}" . PHP_EOL; ???}}//扩展日志功能trait Loggable{ ???protected $logger; ???/** ????* 记录日志 ????* @param DemoLogger $logger ????*/ ???public function setLogger(Logger $logger) ???{ ???????$this->logger = $logger; ???} ???/** ????* 读取日志 ????* @param string $message ????* @param int $level ????*/ ???public function getLog(string $message, int $level) ???{ ???????$this->logger->log($message, $level); ???} ???public function test() ???{ ???????echo ‘trait test‘ . PHP_EOL; ???}}//基类class Base{ ???public static $className = ‘Base‘; ???public function test() ???{ ???????echo static::getClassName() . ‘ test‘ . PHP_EOL; ???} ???//获取类名称 ???public static function getClassName(): string ???{ ???????//return self::$className; ???????return static::$className;//static延时静态绑定 ???}}class Foo extends Base{ ???public static $className = ‘Foo‘; ???use Loggable;}$foo = new Foo;$foo->setLogger(new Logger);$foo->getLog(‘trait works‘, 1);//打印日志信息$foo->test(); //trait test
分析这里 $foo->test()
- Foo类中使用use Loggable来扩展Foo类增加日志功能;
- Trait Loggable类中含有test()方法;
- Foo类继承Base类,其中Base类中含有test();
- 那么问题来了:$foo->test()到底调用的是继承自父类test(),还是Trait类中的test()?
Trait优先级
当前类的函数会覆盖 trait 的同名函数,trait 会覆盖父类的同名函数( use trait 相当于当前类直接覆写了父类的同名函数)
因此,$foo->test()调用的是Trait类中的方法
PHP之Trait特性
原文地址:http://blog.51cto.com/phpme/2128536