我可以强制子类使用父类的构造函数吗?

时间:2010-11-08 03:45:15

标签: php inheritance constructor

当我试图弄清楚为什么没有调用构造函数时,我正在学习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();

3 个答案:

答案 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.