促进水平代码重用的特性
假设我们有一个用于记录的界面:
interface Logger {
function log($message);
}
现在说我们有两个具体的 Logger 接口实现:FileLogger 和 ConsoleLogger。
class FileLogger implements Logger {
public function log($message) {
// Append log message to some file
}
}
class ConsoleLogger implements Logger {
public function log($message) {
// Log message to the console
}
}
现在,如果你定义了一些你也希望能够执行日志记录任务的其他类 Foo,你可以这样做:
class Foo implements Logger {
private $logger;
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
public function log($message) {
if ($this->logger) {
$this->logger->log($message);
}
}
}
Foo 现在也是一个 Logger,但它的功能取决于通过 setLogger() 传递给它的 Logger 实现。如果我们现在希望类 Bar 也具有这种日志记录机制,我们将不得不在 Bar 类中复制这段逻辑。
可以定义一个特征,而不是复制代码:
trait LoggableTrait {
protected $logger;
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
public function log($message) {
if ($this->logger) {
$this->logger->log($message);
}
}
}
现在我们已经在 trait 中定义了逻辑,我们可以使用 trait 将逻辑添加到 Foo 和 Bar 类:
class Foo {
use LoggableTrait;
}
class Bar {
use LoggableTrait;
}
并且,例如,我们可以像这样使用 Foo 类:
$foo = new Foo();
$foo->setLogger( new FileLogger() );
//note how we use the trait as a 'proxy' to call the Logger's log method on the Foo instance
$foo->log('my beautiful message');