当我试图弄清楚为什么没有调用构造函数时,我正在学习PHP并发现了一些令人惊讶的行为。
<?php
class Shape {
function __construct() {
echo 'Shape.';
}
}
class Triangle extends Shape {
function __construct() {
echo 'Triangle';
}
}
$tri = new Triangle();
?>
我习惯了java,所以我认为这会输出“Shape.Triangle”。令人惊讶的是,它只输出“三角形”。我搜索了这个问题,显然我可以通过将parent::__construct();
放在子类中来解决这个问题,但这似乎并不理想。我可以对Shape类做些什么来确保子类总是调用父构造函数吗?每当父有一个构造函数时,我是否真的必须在每个孩子的类中编写parent::__construct();
?
答案 0 :(得分:10)
如果在子类中定义了同名的方法,则会覆盖父方法,并且在任何情况下都不会调用父方法,除非您明确地这样做。即:不,你无能为力,你必须明确地致电parent::__construct()
。
答案 1 :(得分:10)
从PHP 5开始,您可以使用final keyword来阻止父方法被覆盖。
<?php
class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}
final public function moreTesting() {
echo "BaseClass::moreTesting() called\n";
}
}
class ChildClass extends BaseClass {
public function moreTesting() {
echo "ChildClass::moreTesting() called\n";
}
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
您可以将它与预定义的init()
方法结合使用,以确保调用您的父构造函数。
<?php
abstract class Shape {
final function __construct() {
$this->init();
echo 'Shape.';
}
abstract public function init();
}
class Triangle extends Shape {
function init() {
echo 'Triangle';
}
}
$tri = new Triangle();
这将输出
TriangleShape.
如果您记录init()
方法的作用以及在父级中调用它的位置,建议仅使用这样的设计。
答案 2 :(得分:2)
根据PHP手册:
Parent constructors are not called implicitly if the child class defines
a constructor. In order to run a parent constructor, a call to
parent::__construct() within the child constructor is required.