|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2012-05-07 18:40 UTC] postmaster at greg0ire dot fr
Description: ------------ Restraining the __construct() method un a subtype gives a Fatal error. As stated in the following resources, the LSP should not apply here. - https://bugs.php.net/bug.php?id=40880 - http://stackoverflow.com/questions/5490824/should-constructors-comply-with-the-liskov-substitution-principle - http://ralphschindler.com/2012/03/09/php-constructor-best-practices-and-the-prototype-pattern Test script: --------------- <?php class Foo { public function __construct(){} } class Bar extends Foo { protected function __construct(){} } Expected result: ---------------- No output at all. Actual result: -------------- > PHP Fatal error: Access level to Bar::__construct() must be public (as in class Foo) in /tmp/bug.php on line 9 > Fatal error: Access level to Bar::__construct() must be public (as in class Foo) in /tmp/bug.php on line 9 PatchesPull Requests
Pull requests:
HistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Oct 29 04:00:01 2025 UTC |
It's true that PHP's behavior doesn't make a lot of sense from a theoretical perspective. However, there are some practical reasons why a different behavior would be -- arguably -- less desirable. Namely, in PHP the constructor can be called from every instance method, even after construction. This makes it a necessity that the constructor act like regular instance methods. Consider: <?php class A { private $a; function __construct() { $this->a = new stdclass; } function reset() { $this->__construct(); } } class B extends A { private function __construct() { } //what of reset() now? } Plus, PHP allows enforcing constructor signatures via interfaces. This means you have to enforce that signature throughout the hierarchy, and this includes not allows changing the visibility of the constructor. Similarly, there's no principled reason to be unable to reduce the visibility in static methods. But PHP also prohibits such a pattern, like Java does, even though there's no overriding (the method in the superclass is said to be hidden). But PHP, like Java, allows calling static methods through an instance and through the subclass name. Then if you call the reduced visibility static method with the subclass name or a subclass instance, what would you do? Would it depend on the access of the caller has to the subclass method?There are some weak arguments here... <?php class A { private $a; function __construct() { $this->a = new stdclass; } function reset() { $this->__construct(); } } class B extends A { private function __construct() { } //what of reset() now? } Totally trivial case that fails to show anything at all. In reality child constructor can have significantly different arguments and there are no complaints about that (as it should be), and now supposedly such contrived case should mean anything? Why is LSP out with regards to arguments and not with regards to access level? This makes absolutely no sense! Also someone somewhere was talking about how php would not know which constructor to call if child's one is private, if anyone wants to repeat this, this is also nonsense. new B() --> Access exception, you see private constructor, stop looking, no need to dig to parents as that would just lead to incorrect behavior anyways.