有没有办法为特征中的属性提供默认对象?
trait myTrait{
private $foo = 0; // works
private $bar = new stdClass(); // doesn't work.
}
我知道将具体对象实例化为默认值(由于高耦合)似乎是一种糟糕的编码风格。这里的想法是为可选的依赖项提供NullObject。
一个更好的例子(我正在考虑的那个):
使用特征进行记录,并将PSR-3 Logging的默认NullLogger
默认为默认属性:
trait LoggerTrait{
/**
* @var Psr\Log\LoggerInterface
*/
protected $logger;
public function setLogger(Psr\Log\LoggerInterface $logger){
$this->logger = $logger;
}
}
class Foo{
use LoggerTrait;
public function __construct(){
$this->setLogger(new Psr\Log\NullLogger()); // I would like to avoid this line as I'd need to duplicate it in every class I'm using the LoggerTrait.
}
public function doStuff(){
$this->logger->info("Yey flexible logging with no overhead!");
}
}
这有效,但我必须在每个使用该特征的类中明确设置NullLogger
,我想避免这种“代码重复”。
PS:我相信有人会提出记录器也可以通过DI容器插入。这是事实,但不是真的有必要。有关一些赞成/反对论点,请参阅此blog post + comments:)
答案 0 :(得分:1)
解决此问题的常用方法是在类中使用getter
,即使该类拥有该属性。
trait LoggerTrait{
/**
* @var Psr\Log\LoggerInterface
*/
protected $logger;
public function setLogger(Psr\Log\LoggerInterface $logger){
$this->logger = $logger;
}
public function getLogger()
{
if(null === $this->logger) {
$this->logger = new Psr\Log\NullLogger();
}
return $this->logger;
}
}
这样,默认对象甚至不会被实例化,直到需要它为止。
class Foo{
use LoggerTrait;
public function doStuff(){
$this->getLogger()->info("Yey flexible logging with no overhead!");
}
}