促进水平代码重用的特性
假设我们有一个用于记录的界面:
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');