我经常在类中使用存储选项数组的属性。我希望能够以某种方式从父类中声明的默认值中合并这些选项。
我用一些代码来演示。
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
的行为?这样我就不必总是在所有子类中实现相同的代码。 - 我可以使用反射自动找到数组属性在两个类和合并它们?
除了前面的答案之外,另一种可能适合于某些情况的方法是使用PHP Reflection或内置类函数。下面是使用后者的一个基本示例:
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
我意识到我将您的接口从公共变量更改为方法,但也许它适合您。注意,如果您允许父操作继续合并,则添加幼稚的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
)
您可以使用如下的简单模式:
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有一个合并变量的函数。它用于控制器属性,如组件、助手等。但是要小心地将这个函数应用于非常重要的数组—您可能会发现它并不能完全满足您的要求。