我的问题是关于面向对象PHP的继承机制。如果我想在其构造函数中的超类中初始化类变量,并且所有子类都使用初始化变量,我不能在超类的构造函数中执行此操作,因为超类构造函数不会被隐式调用子类构造函数,如Java中所示。如果我必须从每个子构造函数手动调用超类构造函数,我没有任何好处,只需在每个子类构造函数中进行初始化。
我该如何解决这个问题?有什么想法吗?
class superclass {
protected $a;
function __construct() {
$this->a = new Foo();
}
}
class childrenclass1 extends superclass {
function __construct() {
do_something;
}
function childrenfunction() {
$this->a->method(); // not initalized;
}
}
答案 0 :(得分:2)
与Java一样,只有在子类没有实现自己的构造函数时才会自动调用超类构造函数。或者,如果初始属性值是常量表达式,则可以将其声明为类定义的一部分。
所以,基本上,你的选择是:
在父类中使用非动态值初始化变量:
protected $var = 123;
在实现自己的构造函数的所有子类中使用parent::__construct()
。这仍然比在每个子类中初始化这些属性更好,因为使用父的构造函数不会重复代码。
如果继承深度为2(即只有父级和子级),则可以删除子构造函数并定义初始化方法:
class Parent
{
public function __construct()
{
...
$this->initialize();
}
protected function initialize() {}
}
class Child extends Parent
{
protected final function initialize()
{
...
}
}
答案 1 :(得分:0)
不在每个子类构造函数中进行初始化的好处是初始化它的逻辑可以保存在父构造函数中的单个位置。从每个子构造函数中调用父构造函数可能很乏味,但至少它不会重复逻辑。
您的另一个选择是将变量设为私有,并使用方法从子类访问它。如果需要,该方法可以初始化它,然后返回值。
class superclass {
private $a;
protected function getA() {
if (!($this->a instanceof Foo)) {
$this->a = new Foo();
}
return $this->a;
}
}
class childrenclass1 extends superclass {
public function childrenfunction() {
$this->getA()->method();
}
}
...不要忘记使用$this
访问您的变量或方法。你不能像在Java中那样把它留在PHP中。
答案 2 :(得分:0)
调用父构造函数是一个好习惯,因为它可以初始化一些变量或执行其他有用的操作。但是,如果您不想在任何子构造函数parent :: __ construct()中编写,则可以避免使用write子构造函数并将所有内容移动到特殊方法init。它看起来像:
class A {
public function __construct() {
do smt
}
}
class B extends A {
public function init() {
do smt
}
}
$b = new B();
$b->init();