note 50246 added to language.oop5.decon

From: Date: Tue, 22 Feb 2005 22:00:19 +0000
Subject: note 50246 added to language.oop5.decon
Groups: php.notes 
Request: Send a blank email to php-notes+get-85392@lists.php.net to get a copy of this message
(Referring to the earlier example code and comment) The "final" keyword forbids the Baz object to define its own constructor; defining an override for a "final" method creates a fatal error. Without the "final" keyword, if the Baz object defines a constructor, the Foo constructor will not be called automatically; instead, the Baz constructor will be called and the Foo constructor will not. If the Foo constructor SHOULD be called, e.g. to open files or initialise member variables, Baz will need to call parent::__construct() explicitly. In most cases, this is what you will want to do when extending a class, but you can't just do it as a matter of habit... because if Foo does not HAVE a constructor, parent::__construct() is a fatal error. This creates a problem. (The problem can be easily solved with @parent::__construct(), if you don't care about OTHER errors that might arise.) So given an object Foo with no constructor, any extension objects MUST NOT call parent::__construct() in their own constructors. If Foo later *adds* a constructor, the extension objects SHOULD call parent::__construct() if they have constructors themselves. (If they don't, Foo's constructor will be called automatically.) A whole slew of problems pop up as a result, so what we need is a way to say "call the parent class constructor if there is one". An immediate avenue presents itself with is_callable(array("parent","__construct")), but this isn't as useful as you might expect because it doesn't handle old-style constructors. Basically, if Foo has a constructor named Foo(), parent::__construct() will call parent::Foo(), but is_callable(array("parent","__construct")) returns FALSE. Fortunately, this is easily resolved with a call to is_callable(array("parent",get_parent_class($this))). Adding that bit of code into the constructor of your derived classes will achieve exactly what we want, namely to call the parent's constructor if there is one. But there always seems to be a catch... this only works one level down. If Baz extends Bar extends Foo, this code will get Baz to call Bar's constructor, but Bar can't call Foo's constructor with it -- because $this is an instance of Baz, not Bar, so Bar cannot determine its parent class name correctly. (It is noteworthy that if Bar does not *have* a constructor, Baz will still happily pass a request through to Foo's constructor.) The reflection interface is the most obvious way to go about fixing this, but that gets a little too complex to be called a "note". ---- Manual Page -- http://www.php.net/manual/en/language.oop5.decon.php Edit -- http://master.php.net/manage/user-notes.php?action=edit+50246 Delete: added to the manual -- http://master.php.net/manage/user-notes.php?action=delete+50246&report=yes&reason=added+to+the+manual Delete: bad code -- http://master.php.net/manage/user-notes.php?action=delete+50246&report=yes&reason=bad+code Delete: spam -- http://master.php.net/manage/user-notes.php?action=delete+50246&report=yes&reason=spam Delete: useless -- http://master.php.net/manage/user-notes.php?action=delete+50246&report=yes&reason=useless Delete: other reasons -- http://master.php.net/manage/user-notes.php?action=delete+50246&report=yes Reject -- http://master.php.net/manage/user-notes.php?action=reject+50246&report=yes Search -- http://master.php.net/manage/user-notes.php

« previous php.notes (#85392) next »