如果我有一个由很多很多其他类扩展的父类,并且我想确保父类的构造函数总是运行,那么声明构造函数final
是不是一个坏主意? / p>
我在考虑做这样的事情:
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>';
}
}
这样子类可以有一个排序构造函数,父类的构造函数将始终执行。这是不好的做法吗?
答案 0 :(得分:9)
声明final
__construct
可确保任何扩展您的类的人都无法实现具有相同名称的方法。从表面上看,这似乎意味着没有其他人可以为这个类的子类声明构造函数,但事实并非如此,因为{4}的PHP 4样式仍然可以正常工作构造函数的备用名称。实际上,将构造函数声明为final可以在PHP中找不到任何东西。
答案 1 :(得分:5)
从PHP 5.3.3开始,我已经使用5.6和7.0对此进行了测试,声明类__construct
的{{1}}方法将阻止任何子类使用final
覆盖构造函数或PHP 4样式的__construct
(请注意PHP 7样式自PHP 7起已弃用)。防止声明构造函数的子类将确保始终调用父构造函数。当然,这将不允许任何子类实现自己的构造函数逻辑。虽然我不建议将其作为良好做法,但肯定会有实际用例。
一些例子:
未声明ClassName()
最终版
__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()
答案 2 :(得分:-1)
在完成构造函数后,您无法将任何变量传递给初始化函数。它强制您的类的用户使用全局变量作为其子类的设置。
在Zend Framework中使用可覆盖的init()是常见的做法,但我从未见过在那里完成构造函数。