multiple extensions to a class
Jeff Shannon
jeff at ccvcorp.com
Mon Jul 12 16:16:48 EDT 2004
Humpty Dumpty wrote:
>From: "David Fraser" <davidf at sjsoft.com>
>
>
>
>>Jeff Shannon wrote:
>>
>>
>>>You might consider making class A into a container of some sort -- i.e.,
>>>give it someplace to store a list of "decorator" objects, and then make
>>>B, C, and D into such decorators (rather than subclasses of A). You'll
>>>have to arrange some way of dispatching messages to A that are intended
>>>for the decorators, and possibly some way for the decorators to talk to
>>>each other.
>>>
>>>
>
>Interesting idea, could be done... how does this differ from the mixin
>approach?
>
>
Mixins are all derived from the parent class. Combining multiple mixins
requires (as you've noted) knowing ahead of time which combinations
you'll need, and creating a derived class that includes all of the
necessary mixins. (Python does include enough facilities that you could
do this at runtime, but I'm personally rather leery about using this
level of deep magic unless it's truly necessary.)
Decorators, on the other hand, are designed to work with a particular
class, but are not linked directly in an inheritance tree. There might
be a fair amount of coupling between the decorator and the class that
it's designed to decorate, but not necessarily. (IIRC, the Gang of Four
used an example based on a windowing toolkit -- a "border" class could
be designed as a decorator; it wouldn't care what variety of "window"
class it was decorating, and the "window" class wouldn't care what
variety of "border" it carried. The communication protocol between them
would be fairly straightforward and wouldn't depend on the specific
implementation of either the decorator or the decorated class.)
>Yes, but you have to be careful with that in terms of cohesion: though you
>want to allow for extendability through plug-ins, you don't want to
>encourage a mish mash of unrelated classes that send messages around. It's a
>technique to keep in mind, but I want to maintain aggregation of logic and
>function and data as much as possible, ie aim for "the right balance" :)
>
>
Definitely a balance to be had, here. On the whole, though, I don't see
an overgrown inheritance tree to be more maintainable than coherent set
of decorators. Whether the classes are related or not makes scant
difference when there's a mish-mash of them sending messages around. ;)
To my mind, an inherited mixin class is conceptually no simpler than an
aggreggated helper class, and depending on the specific application
aggreggated helpers may result in a cleaner, less-cluttered design. In
particular, for the case where varying sets of additional features will
be needed and those needs won't be known until runtime (i.e., your
case), aggreggation is better able to deal with the dynamic nature of
the requirements.
What I'm envisioning is a system wherein class A contains a list of
decorators. You could probably add and remove decorators at will;
certainly it'd be trivial to pass a list of decorators when A is
instantiated. Now, whenever a significant state change occurs in A, it
will iterate over that list, calling a generic method on each decorator
and passing itself as a parameter:
for dec in self.decorators:
dec.Go(self)
Then the Go() method on each decorator can inspect class A for the
attributes that it understands, and act on them as appropriate. This
does require some coupling between A and the decorators, as they must
both follow a particular protocol, but it doesn't require that either
side of the protocol be a specific class. This means that if you later
extend A in another way, all subclasses of A will work with the same set
of decorators that A does... and a complete replacement for A, not
rooted in the same inheritance tree, will work just as well.
Jeff Shannon
Technician/Programmer
Credit International
More information about the Python-list
mailing list