PHP 性状公共和个人(独立)属性范围
PHP Traits common and individual (separate) properties scope
在 traits 中定义的方法可以访问属性的公共范围,就像在同一对象中定义的方法一样,这很有用。但是,有什么方法可以使两个特征使用相同的 属性 名称,但每个 属性 都在不同的范围内,因此 setTwo()
不会覆盖 $this->data
的 trait one
反之亦然?
示例:
<?php
namespace one;
trait one {
public function setOne($data) {
$this->data = $data;
}
public function getOne()
{
return $this->data;
}
}
namespace two;
trait two {
public function setTwo($data) {
$this->data = $data;
}
public function getTwo()
{
return $this->data;
}
}
namespace bar;
class Bar {
use \one\one;
use \two\two;
}
$bar = new Bar;
$bar->setOne(1);
$bar->setTwo(2);
echo "Bar getOne: " . $bar->getOne() . '<br>' . PHP_EOL; // echoes 2 instead of wanted 1
echo "Bar getTwo: " . $bar->getTwo() . '<br>' . PHP_EOL; // overwrites $this->data = 1 with 2
echo "Bar->data: " . $bar->data . '<br>' . PHP_EOL;
我寻找单独作用域的原因是,对于常见属性的名称,例如:sum、result、cache,您可能最终会在组合 class 多个属性时无意中覆盖它们特质。
我唯一想到的是使用由特征组成的中间 class(它有自己的命名空间和范围)并将其作为依赖项传递给其他 class 需要用于中间组合的特性的某些功能。在上面的示例中,我需要两个中介 classes - 一个具有特征一,另一个具有特征二。
除了中间 class 或将每个特征 $this->data
更改为更多自定义名称(例如 $this->dataOne
和 $this->dataTwo
之外,还有其他选择吗?
每个特征都应定义其方法所需的属性。
依赖未定义的属性或在 class 上定义的使用组合特征的属性是一个坏主意。因此,拥有依赖于相同属性的多个特征是 也是 一个坏主意。
从逻辑上讲,每个特征都应该提供工作所需的一切。
此外,特质没有"scope"。使用特征时,就好像特征中的代码被复制到消费class。在您的示例中,setOne()
和 getTwo()
的范围是 Bar
的实例,与在特征中定义的方法无关。
更明智的方法是在特征本身中包含特征所需的任何属性:
例如:
trait CanLog {
private LoggerInterface $logger;
public function error(string $data)
{
$this->logger->error($data);
}
public function alert(string $data)
{
$this->logger->error($data);
}
}
这样一个消费 class 简单地从特征中导入它需要的行为,完成,并且可以在特征提供的属性中注入他们需要的任何东西:
class Bar
{
use CanLog;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
}
在 traits 中定义的方法可以访问属性的公共范围,就像在同一对象中定义的方法一样,这很有用。但是,有什么方法可以使两个特征使用相同的 属性 名称,但每个 属性 都在不同的范围内,因此 setTwo()
不会覆盖 $this->data
的 trait one
反之亦然?
示例:
<?php
namespace one;
trait one {
public function setOne($data) {
$this->data = $data;
}
public function getOne()
{
return $this->data;
}
}
namespace two;
trait two {
public function setTwo($data) {
$this->data = $data;
}
public function getTwo()
{
return $this->data;
}
}
namespace bar;
class Bar {
use \one\one;
use \two\two;
}
$bar = new Bar;
$bar->setOne(1);
$bar->setTwo(2);
echo "Bar getOne: " . $bar->getOne() . '<br>' . PHP_EOL; // echoes 2 instead of wanted 1
echo "Bar getTwo: " . $bar->getTwo() . '<br>' . PHP_EOL; // overwrites $this->data = 1 with 2
echo "Bar->data: " . $bar->data . '<br>' . PHP_EOL;
我寻找单独作用域的原因是,对于常见属性的名称,例如:sum、result、cache,您可能最终会在组合 class 多个属性时无意中覆盖它们特质。
我唯一想到的是使用由特征组成的中间 class(它有自己的命名空间和范围)并将其作为依赖项传递给其他 class 需要用于中间组合的特性的某些功能。在上面的示例中,我需要两个中介 classes - 一个具有特征一,另一个具有特征二。
除了中间 class 或将每个特征 $this->data
更改为更多自定义名称(例如 $this->dataOne
和 $this->dataTwo
之外,还有其他选择吗?
每个特征都应定义其方法所需的属性。
依赖未定义的属性或在 class 上定义的使用组合特征的属性是一个坏主意。因此,拥有依赖于相同属性的多个特征是 也是 一个坏主意。
从逻辑上讲,每个特征都应该提供工作所需的一切。
此外,特质没有"scope"。使用特征时,就好像特征中的代码被复制到消费class。在您的示例中,setOne()
和 getTwo()
的范围是 Bar
的实例,与在特征中定义的方法无关。
更明智的方法是在特征本身中包含特征所需的任何属性:
例如:
trait CanLog {
private LoggerInterface $logger;
public function error(string $data)
{
$this->logger->error($data);
}
public function alert(string $data)
{
$this->logger->error($data);
}
}
这样一个消费 class 简单地从特征中导入它需要的行为,完成,并且可以在特征提供的属性中注入他们需要的任何东西:
class Bar
{
use CanLog;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
}