Re: PHP 5 Object Inheritance
| From: | Jochem Maas | Date: | Sat, 16 Jul 2005 14:14:34 +0000 |
| Subject: | Re: PHP 5 Object Inheritance | ||
| References: | 1 2 3 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-218811@lists.php.net to get a copy of this message | ||
Chris wrote:
Jochem Maas wrote:many of them, may be all? although I'm not sure multiple inheritance is a pre-requist, and I have read plenty of articles that say that MI is plain evil and should be scrapped - at any rate MI gives you functionality which is sometimes very handy but can also be the proverbial rope with which you hang your self (imagine a class hierarchy 4 layers deep where each leaf class inherits from 2-3 base classes in someway, add a few interfaces, etc, etc ... and now you need to make radical changes to one of your base classes ... have fun :-/ ).Chris wrote:Yeah, I understand... Is multiple inheritance something that true OOP languages can do?Hi, I've got a collection of Element classes (about 8 different ones). They are all subclasses of a single parent element. I'm trying to extend their functionality (both the individual classes, and the parent class they inherit). I can extend each Element subclass with it's new specific functionality, but I would also like to add specific functionality to all of the subclasses. Extending the parent element with the new functionality would *seem* to be the way to go, but I can't make it work None of the Subclasses inherit from the extended superclass. Any thoughts? I'd appreciate any ideas.BaseElement |- SubElement1 | \- ExtendedSubElement |- SubElement2 |- SubElement3 |- SubElement4 |- SubElement5 |- SubElement6 |- SubElement7 |- SubElement8 \- ExtendedBaseElement ExtendedSubElement will never be able to inherit from ExtendedBaseElement. there is no multiple inheritance in php.
maybe the Form object (some kind of controller) should be the only object that is aware of the DB connection and let it handle the binding/logic/etc - let the Element classes just worry about what they have to display and how (i.e. build them do they don't careSo either change your 'tree': BaseElement \- ExtendedBaseElement |- SubElement1 | \- ExtendedSubElement |- SubElement2 |- SubElement3 |- SubElement4 |- SubElement5 |- SubElement6 |- SubElement7 |- SubElement8 ... stick the functionality of ExtendedBaseElement into BaseElement and get rid of the ExtendedBaseElementI can't change the tree, because the non-extended elements still need to be able to function independantly.... or figure out a neat way to use the 'Decorator Pattern' (http://www.google.com/search?q=Decorator+Pattern) in order to conditionally make extended functionality available in specific descendant classes?That seems like it would work, but itdoesn't feel very clean. I'll look into some more.otherwise post some code (cutdown :-) for people to look at.Well, here is my actual tree with all the internals pulled out: <?php abstract class CForm_Element {} class CForm_Datetime extends CForm_Element {} class CForm_File extends CForm_Element {} abstract class CForm_StandardElement extends CForm_Element {}class CForm_Hidden extends CForm_StandardElement {} class CForm_Checkbox extends CForm_StandardElement {} class CForm_Radio extends CForm_StandardElement {} class CForm_Select extends CForm_StandardElement {} class CForm_Textarea extends CForm_StandardElement {} class CForm_Text extends CForm_StandardElement {} class CForm_Password extends CForm_Text {} class CForm_Email extends CForm_Text {} class CForm_Timestamp extends CForm_Text {} abstract class CForm_Number extends CForm_Text {} class CForm_Float extends CForm_Number {} class CForm_Integer extends CForm_Number {}?> They are the elements of a Form Object, to create the form and validate the input. The extended classes I'm working on now associate a database table with the Form object, and will Create, Delete, and Update rows in a database.
This is my currently anticpated Structure. <?php abstract CAdminForm_Element {} CAdminForm_Boolean {} CAdminForm_Email {} CAdminForm_File {} CAdminForm_Float {} CAdminForm_Integer {} CAdminForm_Password {} CAdminForm_Select {} CAdminForm_String {} ?> When I was typing out this structure I realized that some of those have 2 possible objects they'll need to inherit from, which furtherclasses not objects. given the way php works if your objects _need_ to inherit from two or more classes (or one of many, to be decided at run time) then you design is wrong (atleast wrong is so far as your chosen language is not capable of implementing the design!).
complicates things.maybe you should be looking at Interfaces?
An example: I'll want the CAdminForm_Boolean to optionally be Yes/No Radio buttons, or a Checkbox. Which is handled with two separate Form Elements.how you display something shouldn't really affect its definition (whether you show a checkbox or radiobutton is irrelevant - the underlying 'field' is still a 'boolean'). so maybe the instance of CAdminForm_Boolean should state how it would like to be displayed? $myBoolElement->getDisplayType() which could be a std method for all Elements (and would probably return null or 'default' or something similar for most classes), setting the displayType woiuld be a matter of passing an arg to the constructor (or something similar) when you are ... building the form / binding the Elements to DB fields / etc.
I'm *this* close to concluding that it would be better to not extend anyshouldn't that be "I'm $this close" ;-)
of the new AdminForm classes from any of the old, but rather instantiate a Form Element class for each AdminForm Element, then use __call() toyou said the "decorator" pattern didn't seem very clean, until you realise that __call() provides a splendidly clean way of implementing something that looks very much like 'decoration' :-)
pass methods through to the instantied, while overriding the necessary methods in almost the normal way.__call() will not intercept call to method that actually exist (also tru when the method exists in a base class) anyway HTH, Jochem
Thanks for your time, Chris