促進水平程式碼重用的特性
假設我們有一個用於記錄的介面:
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');