7

我经常在我的类中使用存储一系列选项的属性。我希望能够以某种方式将这些选项与父类中声明的默认值合并。

我用一些代码进行了演示。

class A
{
    public $options = array('display'=>false,'name'=>'John');
}

class B extends A
{
    public $options = array('name'=>'Mathew');
}

现在,当我创建时B,我想$options包含一个来自的合并数组A::options

现在发生的事情是这样的。

$b = new B();
print_r($b);
array('name'=>'Mathew');

我想要这样的东西使用array_merge_recursive()

array('display'=>false,'name'=>'Mathew');
  • 也许这是我可以在构造函数中做的事情?
  • 是否有可能使它成为一种行为class A?这样我就不必总是在所有子类中实现相同的代码。
  • 我可以使用反射在两个类中自动查找数组属性并将它们合并吗?
4

3 回答 3

6

除了前面的答案之外,另一种可能适合某些情况的方法是使用 PHP 反射或内置类函数。这是使用后者的基本示例:

class Organism
{
    public $settings;
    public $defaults = [
        'living' => true,
        'neocortex' => false,
    ];
    public function __construct($options = [])
    {
        $class = get_called_class();
        while ($class = get_parent_class($class)) {
            $this->defaults += get_class_vars($class)['defaults'];
        }
        $this->settings = $options + $this->defaults;
    }
}
class Animal extends Organism
{
    public $defaults = [
        'motile' => true,
    ];
}
class Mammal extends Animal
{
    public $defaults = [
        'neocortex' => true,
    ];
}

$fish = new Animal();
print_r($fish->settings); // motile: true, living: true, neocortex: false
$human = new Mammal(['speech' => true]);
print_r($human->settings); // motile: true, living: true, neocortex: true, speech: true
于 2016-04-22T05:44:11.543 回答
4

我意识到我将您的接口从公共变量更改为方法,但也许它对您有用。setOps($ops)请注意,如果您允许继续合并父操作,则添加天真的方法可能会出乎意料。

class A
{
    private $ops = array('display'=>false, 'name'=>'John');
    public function getops() { return $this->ops; }
}
class B extends A
{
    private $ops = array('name'=>'Mathew');
    public function getops() { return array_merge(parent::getOps(), $this->ops); }
}
class c extends B
{
    private $ops = array('c'=>'c');
    public function getops() { return array_merge(parent::getOps(), $this->ops); }
}

$c = new C();
print_r($c->getops());

出去:

Array
(
    [display] => 
    [name] => Mathew
    [c] => c
)
于 2013-01-19T18:56:50.103 回答
2

您可以使用这样的简单模式:

abstract class Parent {

    protected $_settings = array();

    protected $_defaultSettings = array(
        'foo' => 'bar'
    );

    public __construct($settings = array()) {
        $this->_settings = $settings + $this->_defaultSettings;
    }

}

通过这种方式,很容易修改子类中应用的默认值:

class Child extends Parent {

    protected $_defaultSettings = array(
        'something' => 'different';
    );

}

或者应用更复杂的东西:

class OtherChild extends Parent {

    function __construct($settings = array()) {
        $this->_defaultSettings = Configure::read('OtherChild');
        return parent::__construct($settings);
    }

}

合并变量

Cake 确实带有合并变量的功能。它用于控制器属性,例如组件、助手等。但要小心将此函数应用于非平凡的数组 - 您可能会发现它并不能完全满足您的需求/期望。

于 2013-01-19T18:42:35.050 回答