3

我有以下类层次结构,如下面的复制脚本所示:

<?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有没有办法在没有(后期静态绑定)的情况下实现类树的合并效果?

4

4 回答 4

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为空数组,您可以像上面那样使用数组运算符来简化代码。中未定义的键$config由 填充$this->defaults

扩展类看起来非常相似:

class B extends A
{
    private $defaults = array(
        'param3' => 1
    );

    public function __construct(array $config = array())
    {
        parent::__construct($config + $this->defaults);
    }
}
于 2013-07-23T07:27:09.187 回答
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);
    }
}
于 2013-07-23T06:32:10.820 回答
3

您可以使用ReflectionClass. 首先 introspecting $this, use getProperty(),然后 usegetParentClass()对父类及其父类等执行相同操作,并将结果数组合并在一起。

不过,这可能不是您面临的问题的最佳解决方案。

于 2013-07-23T06:34:41.553 回答
1

我相信以下是您正在寻找的。改编自继承子类中的静态属性而不重新声明?

<?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, ) 
于 2015-12-04T23:49:43.200 回答