Reputation: 4715
I have two classes Foo
and Bar
that Bar
extends Foo
as below:
class Foo {
protected
$options = array(),
$defaults = array(1, 2);
public function __construct($options){
array_push($this->options, $this->defaults);
}
}
class Bar extends Foo {
protected $defaults = array(3, 4);
public function print(){
print_r($this->$options);
}
}
$bar = new Bar();
$bar->print();
i thought that result should be array(1,2,3,4)
but is array(3,4)
.
how to solve that ?
edit
i don't want Bar class to have constructor because i'm just implementer of superclass and don't know what really will happen in child class.
Upvotes: 0
Views: 207
Reputation: 4143
"I just want each child class could have it's default values".
You want to have specific data for each class.
You can use "static fields", make class act as a variable, by itself. Im not very fan of "static members", but I think, it applies to your "use case".
class Foo {
private
// (1) "private" only accessed by the class itself,
// neither external code, or subclasses,
// (2) "static", specific to the class,
static $defaults = array(1, 2);
protected
// want to be accessed only by class & subclasses
$options = array();
// when using "static fields" in constructor,
// you need to override constructor
public function __construct($options){
array_push($this->options, Foo::$defaults);
}
// ops, "print" is reserved identifier
// public function print(){
public function display_options() {
print_r($this->$options);
}
public function display_defaultoptions() {
// in order to acccess "static fields",
// you use the class id, followed by double colon,
// not "$this->*"
print_r(Foo::$defaults);
}
} // class Foo
class Bar extends Foo {
private
// (1) "private" only accessed by the class itself,
// neither external code, or subclasses,
// (2) "static", specific to the class,
static $defaults = array(1, 2);
// when using "static fields" in constructor,
// you need to override constructor
public function __construct($options){
array_push($this->options, Bar::$defaults);
}
public function display_defaultoptions() {
// in order to acccess "static fields",
// you use the class id, followed by double colon
// not "$this->*"
print_r(Bar::$defaults);
}
} // class Bar
$bar = new Bar();
$bar->print();
Cheers
Upvotes: 0
Reputation: 24671
First- You cannot have a method named print
. print
is a language construct and cannot be overridden.
Second- you should make the default values for a class private, and override them in child classes. Then you can combine them in the parent when you call the constructor. It's not 100% clear what you're trying to accomplish, but the following will merge the sub-class' default options with the superclass':
Updated to remove constructor
abstract class Foo {
protected $options = array();
private $defaults = array(1, 2);
// Implementations of this class MUST define this method
abstract function overrideDefaults();
public function __construct($options = array()){
// Merge any incoming options with the default options
$this->options = array_merge($this->defaults, $options);
}
// Concrete children can use this method to modify the current options by
// passing in their own defaults.
protected function modifyDefaults( $defaults ) {
$this->options= array_merge( $this->defaults, $defaults );
}
public function printOps(){
print_r($this->options);
}
}
class Bar extends Foo {
private $defaults = array(3, 4);
public function overrideDefaults() {
parent::modifyDefaults( $this->defaults );
}
}
$bar = new Bar();
$bar->overrideDefaults();
$bar->printOps();
Notice I also moved the now printOps
method to the superclass. Output:
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
Upvotes: 1
Reputation: 175098
There are a couple of solutions, the simplest would be a second variable to be used as an extended defaults, then merge the arrays.
class Foo {
protected
$options = array(),
$original_defaults = array(1, 2),
$extended_defaults = array();
public function __construct($options){
array_merge($this->extended_defaults, $this->original_defaults);
array_push($this->options, $this->original_defaults);
}
}
class Bar extends Foo {
protected $extended_defaults = array(3, 4);
public function print(){
print_r($this->$options);
}
}
$bar = new Bar();
$bar->print();
Upvotes: 2
Reputation: 38485
Why would it combine your arrays?
You set $defaults
to (1,2)
and then to (3,4)
- nowhere are you concatenating them.
Your constructor adds (1,2)
onto $options
. That's all it does.
Your print method outputs $defaults
which at this point would be (3,4)
because you initialise them as a protected var.
Upvotes: 2
Reputation: 219924
If you don't want those values to be overridden then use private
instead of protected
. This will prevent subclasses from overriding those values.
Upvotes: 1