我有一个以下的类层次结构,它显示在下面的复制脚本中:
<?php
header('Content-Type: text/plain');
class A
{
public $config = array(
'param1' => 1,
'param2' => 2
);
public function __construct(array $config = null){
$this->config = (object)(empty($config) ? $this->config : array_merge($this->config, $config));
}
}
class B extends A
{
public $config = array(
'param3' => 1
);
public function __construct(array $config = null){
parent::__construct($config);
// other actions
}
}
$test = new B();
var_dump($test);
?>
输出:
object(B)#1 (1) {
["config"]=>
object(stdClass)#2 (1) {
["param3"]=>
int(1)
}
}
我想要的是A::$config
不能被B::$config
覆盖。 B
可能有很多后代类,我想更改$config
,但如果匹配$config
值,我需要合并/覆盖那些$config
值所有这些都是父母。
问:我该怎么做?
我尝试使用array_merge()
,但在非静态模式下,这些变量只会覆盖它们自己。有没有办法在没有static
(后期静态绑定)的情况下实现类树的合并效果?
答案 0 :(得分:4)
最好将这些值声明为默认值,而不是使用您将在构造函数中更改的值声明$config
属性。 Orangepill的回答中也描述了这一点:
class A
{
public $config;
private $defaults = array(
'param1' => 1,
'param2' => 2,
);
public function __construct(array $config = array())
{
$this->config = (object)($config + $this->defaults);
}
}
那里有几个曲折;通过将$config
构造函数参数的默认值声明为空数组,您可以像上面一样使用array operators来简化代码。 $config
中未定义的密钥由$this->defaults
填写。
扩展类看起来非常相似:
class B extends A
{
private $defaults = array(
'param3' => 1
);
public function __construct(array $config = array())
{
parent::__construct($config + $this->defaults);
}
}
答案 1 :(得分:3)
您可以重新构建扩展类的实例化方式
class B extends A
{
private $defaults = array('param3' => 1);
public function __construct(array $config = null){
parent::__construct($config?array_merge($this->defaults, $config):$this->defaults);
}
}
答案 2 :(得分:3)
您可以使用ReflectionClass
执行此操作。首先内省$this
,使用getProperty()
,然后使用getParentClass()
在父类及其父级等上执行相同的操作,并将生成的数组合并在一起。
这可能不是您遇到的问题的最佳解决方案。
答案 3 :(得分:1)
我相信您正在寻找以下内容。改编自Inherit static properties in subclass without redeclaration?
<?php
class MyParent {
public static $config = array('a' => 1, 'b' => 2);
public static function getConfig() {
$ret = array();
$c = get_called_class();
do {
$ret = array_merge($c::$config, $ret);
} while(($c = get_parent_class($c)) !== false);
return $ret;
}
}
class MyChild extends MyParent {
public static $config = array('a' => 5, 'c' => 3, 'd' => 4);
public function myMethod($config) {
$config = array_merge(self::getConfig(), $config);
}
}
class SubChild extends MyChild {
public static $config = array('e' => 7);
}
var_export(MyChild::getConfig());
// result: array ( 'a' => 5, 'b' => 2, 'c' => 3, 'd' => 4, )
$mc = new MyChild();
var_export($mc->myMethod(array('b' => 6)));
// result: array ( 'a' => 5, 'b' => 6, 'c' => 3, 'd' => 4, )
var_export(SubChild::getConfig());
// result: array ( 'a' => 5, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 7, )