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