【问题标题】:Can I force a child class to use the parent's constructor?我可以强制子类使用父类的构造函数吗?
【发布时间】:2011-05-06 11:40:33
【问题描述】:

我正在学习 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();吗?

【问题讨论】:

标签: php inheritance constructor


【解决方案1】:

从 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】:

    如果您在子类中定义了同名方法,则父类的方法将被覆盖,并且在任何情况下都不会被调用,除非您明确这样做。即:不,您无能为力,您必须明确致电parent::__construct()

    【讨论】:

    • 您还可以让父级声明父级构造函数调用的抽象或空初始化方法。
    • @erisco 这将是一个很好的设计模式来解决这个问题,但它不会改变事实。 :)
    • @deceze 最初的问题确实询问了有关模拟特定行为的问题......实际上可以模拟。
    • @Mirrored 我不会说使用final 并指定另一个方法作为构造函数是一个很好的选择。如果您想扩展扩展类并确保运行 its 替代构造函数怎么办?这不是一个非常可扩展的解决方案。默认的 PHP 习惯用法是使用parent。这样做是每个开发人员的决定和责任。
    • @deceze 我也不会说这是一个“很棒”的选择,而且可能不适合大多数情况。但说“你无能为力”是不正确的
    【解决方案3】:

    根据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. 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多