9

如果我有一个由许多其他类扩展的父类,并且我想确保父类的构造函数始终运行,那么声明构造函数是一个坏主意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>';

    }

}

这样子类可以有某种构造函数,而父类的构造函数将始终执行。这是不好的做法吗?

4

3 回答 3

10

声明 afinal __construct可确保扩展您的类的任何人都不能实现具有相同名称的方法。从表面上看,这似乎意味着没有其他人可以为此类的子类声明构造函数,但事实并非如此,因为 PHP 4 风格ClassName()的构造函数。真的,将构造函数声明为 final 在 PHP 中没有任何意义。

于 2010-01-03T01:54:59.493 回答
6

从 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

与决赛__construct

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

class ChildClassB extends ParentClassWithFinal {
}

echo (new ChildClassB()); // output: ChildClassB

试图__construct在子类 中声明

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

// Fatal error: Cannot override final method ParentClassWithFinal::__construct()

试图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
于 2016-09-29T01:12:15.960 回答
-1

完成构造函数后,您不能将任何变量传递给初始化函数。它强制您班级的用户使用全局变量作为其子班级的设置。

在 Zend 框架中,使用可覆盖的 init() 是常见的做法,但我从未见过在那里完成构造函数。

于 2010-01-03T01:28:21.787 回答