我有Foo
和Bar
两个类Bar
扩展Foo
,如下所示:
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();
我认为结果应该是array(1,2,3,4)
,但是array(3,4)
怎么解决?
修改
我不希望Bar类有构造函数,因为我只是超类的实现者,不知道在子类中会发生什么。
答案 0 :(得分:2)
有几种解决方案,最简单的是第二个变量用作扩展默认值,然后合并数组。
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();
答案 1 :(得分:2)
为什么它会组合你的阵列?
您将$defaults
设置为(1,2)
,然后设置为(3,4)
- 您无法将它们连接起来。
您的构造函数将(1,2)
添加到$options
。就是这样。
您的打印方法会输出$defaults
,此时(3,4)
将{{1}},因为您将它们初始化为受保护的var。
答案 2 :(得分:1)
如果您不希望覆盖这些值,请使用private
代替protected
。这将阻止子类覆盖这些值。
答案 3 :(得分:1)
首先 - 您不能拥有名为print
的方法。 print
是一种语言结构,无法覆盖。
其次 - 您应该将类的默认值设为private,并在子类中覆盖它们。然后,您可以在调用构造函数时将它们组合在父级中。它并不是100%清楚你要完成的是什么,但以下内容将子类的默认选项与超类合并:
已更新以删除构造函数
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();
注意我还将现在的printOps
方法移到了超类。输出:
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
答案 4 :(得分:0)
“我只想让每个子类都有它的默认值”。
您希望为每个班级提供特定数据。
您可以使用“静态字段”,使类本身充当变量。我不是很喜欢“静态成员”,但我认为,它适用于你的“用例”。
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();
干杯