开发者

Is it bad practice to declare a class's ctor 'final' in PHP?

开发者 https://www.devze.com 2022-12-15 02:48 出处:网络
If I have a parent class that is extended by lots and lots of other classes, and I want to make sure the parent class\'s constructor is ALWAYS run, is it a bad开发者_StackOverflow idea to declare the

If I have a parent class that is extended by lots and lots of other classes, and I want to make sure the parent class's constructor is ALWAYS run, is it a bad开发者_StackOverflow idea to declare the constructor final?

I was thinking of doing something like this:

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>';

    }

}

that way the child class can have a sort-of constructor, and the parent class's constructor will always execute. Is this bad practice?


Declaring a final __construct ensures that no one who extends your class can implement a method with the same name. On the surface of it, this would seem like it would mean no one else can declare a constructor for sub-classes of this class, but this is not true, since the PHP 4 style of ClassName() still works just fine as an alternate name for the constructor. So really, declaring a constructor as final gets you nothing in PHP.


As of PHP 5.3.3, I have tested this with 5.6 and 7.0, declaring the __construct method of a class final will prevent any child class overriding the constructor either using __construct or the PHP 4 style of ClassName() (note that the PHP 4 style is deprecated as of PHP 7). Preventing a child class declaring a constructor will ensure that the parent constructor is always called. This will, of course, not allow any child classes to implement their own constructor logic. There would definitely be practical use cases for this though I would not recommend it as good practice generally.

Some examples:

Without declaring __construct final

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

With final __construct

class ParentClassWithFinal extends ParentClassWithoutFinal {
    public final function __construct() {
        parent::__construct();
    }
}

class ChildClassB extends ParentClassWithFinal {
}

echo (new ChildClassB()); // output: ChildClassB

Trying to declare __construct in a child class

class ChildClassC extends ParentClassWithFinal {
    public function __construct() {
    }
}

// Fatal error: Cannot override final method ParentClassWithFinal::__construct()

Trying to declare ClassName() constructor in a child class

class ChildClassD extends ParentClassWithFinal {
    public function ChildClassD() {
    }
}

// Fatal error: Cannot override final ParentClassWithFinal::__construct() with ChildClassD::ChildClassD()
// Also in PHP 7: Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; ChildClassD has a deprecated constructor


After finalizing the constructor, you can't pass any variables to initializing function. It forces users of you class to use globals as settings for their child classes.

In Zend Framework using overridable init() is common practice, but I've never seen finalizing a constructor there.

0

精彩评论

暂无评论...
验证码 换一张
取 消