How to inherit array properties of parent class by array merge?
I often use properties in my classes that store an array of parameters. I would like to be able to somehow combine these parameters from the default values declared in the parent class.
I have demonstrated with some code.
class A
{
public $options = array('display'=>false,'name'=>'John');
}
class B extends A
{
public $options = array('name'=>'Mathew');
}
Now when I create B
I would like to $options
contain the concatenated array fromA::options
Now this is happening.
$b = new B();
print_r($b);
array('name'=>'Mathew');
I would like something like this with help array_merge_recursive()
.
array('display'=>false,'name'=>'Mathew');
- Maybe this is something I could do in the constructor?
- Can this behavior be done
class A
? So I don't always have to implement the same code in all subclasses. - Is it possible to use reflection to automatically look up array properties in both classes and combine them?
source to share
I realize I changed my interface from a public variable to a method, but maybe it works for you. Be aware that adding a naive method setOps($ops)
can unexpectedly work if you allow parent operations to continue merging.
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());
out:
Array
(
[display] =>
[name] => Mathew
[c] => c
)
source to share
In addition to the previous answers, another approach that might be applicable in some cases would be using PHP Reflection or built-in class functions. Here's a basic example using the latter:
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
source to share
You can use a simple template like:
abstract class Parent {
protected $_settings = array();
protected $_defaultSettings = array(
'foo' => 'bar'
);
public __construct($settings = array()) {
$this->_settings = $settings + $this->_defaultSettings;
}
}
Thus, it is easy to change the default values used in child classes:
class Child extends Parent {
protected $_defaultSettings = array(
'something' => 'different';
);
}
Or apply something more complex:
class OtherChild extends Parent {
function __construct($settings = array()) {
$this->_defaultSettings = Configure::read('OtherChild');
return parent::__construct($settings);
}
}
Merging variables
Cake does have a function for merging variables . It is used for controller properties like components, helpers, etc. But be careful when applying this function to any trivial arrays - you may find that it doesn't quite do what you want / expect.
source to share