本文共 1370 字,大约阅读时间需要 4 分钟。
Trait 本质上是无状态的mixin,是PHP解释器自动完成的『粘贴&拷贝』,区别于继承,它提供的重用是水平性的,很好地提高了代码的可重用。然而错误使用会造成冲突,BUG难以调试。先来看看 trait 的其中一种正确使用方式。
interface Logger{ public function log($message, $level); }class DemoLogger implements Logger{ public function log($message, $level) { echo "Logged message: $message with level $level", PHP_EOL; }}trait Loggable // implements Logger{ protected $logger; public function setLogger(Logger $logger) { $this->logger = $logger; } public function log($message, $level) { $this->logger->log($message, $level); }}class Foo implements Logger{ use Loggable;}
然后我们可以像下面这样使用:
$foo = new Foo;$foo->setLogger(new DemoLogger);$foo->log('It works', 1);
下面是一些错误使用 trait 的范例。
trait T { protected function foo() {}}class A { public function foo() {}}class B extends A{ use T;}
这段代码会因为修改 foo函数的可见性而引起报错。
trait T { public function foo() { return 1;}}class A { use T; public function foo() { return 2;}}$a = new A;echo $a->foo();
上面代码会输出 2,trait 中的定义的方法永远不会得到执行。另外,trait 中不应该调用concrete class的任何方法或者属性,看下面例子:
class A{ use T; protected $prop = 1; protected function getProp() { return $this->prop; }}trait T{ public function foo() { return $this->getProp(); }}$a = new A;echo $a->foo();
上面代码,trait中调用了特定类实例的方法,从而造成 trait 对具体实现类的依赖,丧失了trait代码 的可重用性,这种使用方式是错误的。
转载地址:http://swega.baihongyu.com/