Chris wrote:
Jochem Maas wrote:

Chris wrote:

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.

Yeah, I understand... Is multiple inheritance something that true OOP languages can do?

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 :-/ ).


So 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 ExtendedBaseElement

I 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.

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 care


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 further

classes 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 any

shouldn'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() to

you 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


--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to