在PHP中声明一个类的ctor'final'是不好的做法吗?

Car*_*ers 7 php constructor final class

如果我有一个由很多很多其他类扩展的父类,并且我想确保父类的构造函数总是运行,那么声明构造函数是一个坏主意final吗?

我在考虑做这样的事情:

class ParentClass {

    public final function __construct() {

        //parent class initialization...

        $this->construct();

    }

    protected function init() {

        echo 'constructing<br>';

    }

}

class ChildClass extends ParentClass {

    protected function init() {

        //child class initialization

        echo 'constructing child<br>';

    }

}
Run Code Online (Sandbox Code Playgroud)

这样子类可以有一个排序构造函数,父类的构造函数将始终执行.这是不好的做法吗?

Mik*_*ike 10

声明final __construct确保没有任何扩展您的类的人可以实现具有相同名称的方法.从表面上看,这似乎意味着没有其他人可以为这个类的子类声明构造函数,但事实并非如此,因为PHP 4样式ClassName()仍可以作为替代名称使用构造函数.实际上,将构造函数声明为final可以在PHP中找不到任何东西.


bst*_*ney 5

从PHP 5.3.3开始,我已经用5.6和7.0测试了这一点,声明__construct类的方法final将阻止任何子类覆盖构造函数使用__construct或PHP 4样式ClassName()(注意PHP 4样式从PHP开始不推荐使用7).防止声明构造函数的子类将确保始终调用父构造函数.当然,这将不允许任何子类实现自己的构造函数逻辑.肯定会有实际用例,但我不建议将其作为良好做法.

一些例子:

没有宣布__construct最终结果

class ParentClassWithoutFinal {
    private $value = "default";

    public function __construct() {
        $this->value = static::class;
    }

    function __toString() {
        return $this->value;
    }
}

class ChildClassA extends ParentClassWithoutFinal {
    public function __construct() {
        // Missing parent::__construct();
    }
}

echo (new ChildClassA()); // ouput: default
Run Code Online (Sandbox Code Playgroud)

随着决赛 __construct

class ParentClassWithFinal extends ParentClassWithoutFinal {
    public final function __construct() {
        parent::__construct();
    }
}

class ChildClassB extends ParentClassWithFinal {
}

echo (new ChildClassB()); // output: ChildClassB
Run Code Online (Sandbox Code Playgroud)

试图__construct在子类中 声明

class ChildClassC extends ParentClassWithFinal {
    public function __construct() {
    }
}

// Fatal error: Cannot override final method ParentClassWithFinal::__construct()
Run Code Online (Sandbox Code Playgroud)

试图ClassName()在子类中声明构造函数

class ChildClassD extends ParentClassWithFinal {
    public function ChildClassD() {
    }
}

// Fatal error: Cannot override final ParentClassWithFinal::__construct() with ChildClassD::ChildClassD()
// Also in PHP 7: Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; ChildClassD has a deprecated constructor
Run Code Online (Sandbox Code Playgroud)