最佳实践,重写__construct()与提供init()方法

Gor*_*onM 27 php oop subclassing

当您继承对象并希望扩展初始化代码时,有两种方法.覆盖__construct(),并实现超类构造函数调用的初始化方法.

方法1:

class foo
{
    public function __construct ($arg1, $arg2, $arg3)
    {
        // Do initialization
    }
}

class bar extends foo
{
    public function __construct ($arg1, $arg2, $arg3)
    {
        parent::__construct ($arg1, $arg2, $arg3);
        // Do subclass initialization
    }
}
Run Code Online (Sandbox Code Playgroud)

方法2

class foo
{
    public function init ()
    {
        // Dummy function
    }

    public function __construct ($arg1, $arg2, $arg3)
    {
        // Do subclass defined initialization
        $this -> init ();
        // Do other initialization
    }
}

class bar extends foo
{
    public function init ()
    {
        // Do subclass initialization
    }
}
Run Code Online (Sandbox Code Playgroud)

对于Zend框架的文件似乎阻止重载构造函数,并希望您重写初始化方法,若设置,但不知何故只是不觉得我的权利.Zend还倾向于做一些我不满意的事情,所以我不确定它是否应该被用作最佳实践的一个例子.我个人认为第一种方法是正确的,但我已经看到第二种方法经常足以想知道这实际上是我应该做的.

你对覆盖__construct有什么意见吗?我知道你必须小心记住调用超类构造函数,但大多数程序员应该知道这一点.

编辑: 我没有使用Zend,我只是使用它作为代码库的一个例子,鼓励你使用init()而不是重写__construct().

Fro*_*y Z 18

看起来第二种方法是推迟问题.

如果你有一个班级:

class bar2 extends bar // which already extends foo
{
  public function init()
  {
    // You should then do anyway:
    parent::init();

    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

我也会采用第一种方法,更合乎逻辑,更直接,因为无法无休止地避免使用parent::init()parent::__construct()调用.第一种方法IMO不那么容易混淆.


Gor*_*don 8

我能想到的唯一两种情况init()是使用它是有意义的,当你的构造函数是非公开的,但你需要给人们一个影响初始化的机会,例如在一个抽象的Singleton中(你不想使用它) .或者,像在Zend Framework中一样,应该延迟额外的初始化(但是你不要init()从构造函数调用).

顺便提一下,从超类中调用子类中的方法称为模板方法.UseCase将协调某个工作流程,但允许子类型影响其中的部分工作流程.这通常是通过常规方法完成的.请注意,构造函数不应该编排任何东西,只需将对象初始化为有效状态即可.

你绝对应该叫/报价init()从构造以防止不必记住调用父类的构造函数的开发.虽然这听起来很方便,但很快就会破坏继承层次结构.还要注意,它与通常初始化对象的方式不同,开发人员必须学习这种新行为,就像他们必须学会调用超类型的构造函数一样.