我终于开始在PHP中探索特征了。我认为我尝试的第一个地方是将配置位注入类中。如果我使用DIC,我可能在任何需要配置对象的类中都有这样的代码:
protected function SetConfig($config) {
$this->config = $config;
}
protected $config;
这似乎很适合特性,以避免在整个地方都有样板代码,所以我可能会创建这个:
trait Config {
protected function SetConfig($config) {
$this->config = $config;
}
protected $config;
}
然后像这样使用它:
class Foo {
use Config;
public function __construct() {
//can now use $this->config
}
}
太棒了。现在让我们说我想创建第二个特征,例如,记录:
trait Logger {
protected function SetLogger($logger) {
$this->logger = $logger;
}
protected $logger;
}
我可以这样使用:
class Foo {
use Logger;
public function __construct() {
//can now use $this->logger
}
}
也很棒。现在问题出现了,如果这两个特征想要互相使用。记录器类需要注入一个配置对象似乎是合理的,这意味着这样做:
trait Logger {
use Config;
protected function SetLogger($logger) {
$this->logger = $logger;
}
protected $logger;
}
但是当另一个类使用这两个特征时,事情就会破裂:
class Foo {
use Config, Logger;
public function __construct() {
//want to use $this->config and $this->logger
}
}
当然,这不起作用,因为配置位在Foo中有效复制。
我可以从记录器特征中省略use Config;
件,知道它最终会在那里。但这对我来说很奇怪,因为它创造了一种外在的依赖。如果我想在没有配置特性的情况下使用Logger,该怎么办?这个解决方案也意味着我需要让我的IDE(PhpStorm 8)警告我未知的方法,而不是提供自动完成。我意识到我可以通过使用@method来解决这些问题,但是这只是将口红涂在猪身上,可以这么说。
我也可以在Logger中对配置位进行别名,但这也存在问题。
所有这一切都有一点气味,但我还没有弄清楚是否这是因为这对我来说是一种新模式,或者它是否真的是一种臭味模式。无论哪种方式,我都不确定使这种方法真正起作用的最佳方法。
关于在特征中解决这个问题的最佳方法的任何建议?或者,最好避免DIC快捷方式的特征?
答案 0 :(得分:3)
我发现有用的方法是使用getter和setter。然后,这允许您要求存在特定的getter,而不会与其他特征冲突。
trait Config {
protected function SetConfig($config) {
$this->config = $config;
}
protected function GetConfig() {
return $this->config;
}
protected $config;
}
trait Logger {
abstract protected function GetConfig();
protected function SetLogger($logger) {
$this->logger = $logger;
}
protected $logger;
}
class Baz {
use Config, Logger;
// ...
}
在Baz中,Config特性提供了所需的抽象方法,并且Baz的组合没有错误。如果您错误地仅使用Logger,您将收到致命错误:Class Baz包含1个抽象方法,因此必须声明为abstract或实现其余方法(Baz :: GetConfig)