1

我的问题是关于面向对象 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;
  }

}
4

3 回答 3

2

与 Java 一样,超类构造函数仅在子类未实现自己的构造函数时才会自动调用。或者,如果初始属性值是常量表达式,则可以将它们声明为类定义的一部分。

所以,基本上,你的选择是:

  1. 在父类中用非动态值初始化变量:

    protected $var = 123;
    
  2. parent::__construct()在所有实现自己的构造函数的子类中使用。这仍然比在每个子类中初始化这些属性要好,因为使用父类的构造函数不会重复代码。

如果继承深度为 2(即只有父和子),您可以删除子构造函数并定义一个初始化方法:

class Parent
{
    public function __construct()
    {
        ...
        $this->initialize();
    }

    protected function initialize() {}
}

class Child extends Parent
{
    protected final function initialize()
    {
        ...
    }
}
于 2013-07-20T14:53:36.797 回答
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 中忽略它。

于 2013-07-20T20:02:12.230 回答
0

It's a good practice to call parent constructor because it can initialize some variables or do other usefull things. But if you don't want to write in any child constructor parent::__construct() you can avoid write child constructor and move everything to a special method init. It will look like as:

class A {
    public function __construct() {
        do smt
    } 
}

class B extends A {
    public function init() {
        do smt
    } 
}

$b = new B(); 
$b->init();
于 2013-07-20T20:03:53.003 回答