从基类构造函数中调用扩展类中的方法

时间:2014-01-24 19:16:34

标签: php inheritance

是否有可能从基类构造函数中调用扩展类方法?

以下是我想要做的一个例子:

<?php
class SomeController extends Controller {
    public function init() {
        echo "lol";
    }
}

class Controller {
    public function __construct() {
        // do something to call init() in SomeController.
    }
}

只是想知道这样的事情。

1 个答案:

答案 0 :(得分:1)

超类对它们自己的子类一无所知,除了作为超类的子类强加于子类的约束。如果你考虑一下,这是完全合理的。他们怎么样?开发人员毕竟可以将他们想要的任何内容添加到子类中。

但是,超类可以执行的是强制其子类具有哪些方法。如果某个方法存在于超类中,那么它必须存在于子类中,因为您无法删除子类中的方法。如果您使用具体的超类作为基类,那么您只需实现一个在超类中不执行任何操作的方法,并且所有子类都将拥有它。对于需要在该方法中发生某些事情的任何子类,它们可以使用自己的实现覆盖它。您可以从超类中调用该方法,并确保子类具有它的实现。

为此,该方法不能是私有的。它必须受到保护或公开。

class Controller {

    protected function init () {
        // Do nothing, this method exists only to be overridden
    }

    public function __construct() {
        // do something to call init() in SomeController.
        $this -> init ();
    }
}

如果超类本身存在没有意义,那么你可以使超类init成为一个抽象方法,所以你根本不必提供实现。您只能在抽象类中声明抽象方法,并且无法实例化抽象类。

现在,任何继承自超类的子类都将被强制实现init()方法。如果没有,那么当您尝试运行代码时会发生致命错误。

abstract class Controller {

    abstract protected function init ();

    public function __construct() {
        // do something to call init() in SomeController.
        $this -> init ();
    }
}

与前面的示例一样,这确保了这个子类的所有子类都有一个init()方法,因此从超类中调用init()是安全的。

注意:由于PHP的Zend引擎的实现方式的特殊性,理论上可以在超类不知道子类方法时从超类调用子类方法。然而,这不是一个刻意的设计决定,它是无证的行为。因此可以在任何时候删除它。即使PHP永远保持这种状态,在不知道子类实现该方法的情况下从超类调用子类方法仍然是一种非常糟糕的做法。永远不要依赖那种行为。

相关问题