multiple extensions to a class | | |
Hello, I'm experimenting with different ways of extending a class (for a
plug-ins framework for a GUI) with more than one extension when some of
these extensions need to collaborate, but others mustn't know about each
other.
I.e., if I have a class A, and I want to add a block of functionality, I
can derive it into a B that adds that fucntionality. If I want to add more
functionality, I can derive B into a C. But if I want to add a third bit of
functionality D directly to A, such that D knows nothing about B or C, I
won't be able to instantiate an object that has all three extensions, namely
an "ABCD". It will either be an "ABC" or an "AD".
One possibility would be to define the extensions B,C and D as functions and
add those functions to A with new.instancemethod. Any other ideas on how to
do this? E.g. is it possible to *add* base classes to a class? I could add
the extensions by adding them as base classes to A.
Thanks,
Oliver | | | | re: multiple extensions to a class
Humpty Dumpty wrote:[color=blue]
> Hello, I'm experimenting with different ways of extending a class (for a
> plug-ins framework for a GUI) with more than one extension when some of
> these extensions need to collaborate, but others mustn't know about each
> other.
>
> I.e., if I have a class A, and I want to add a block of functionality, I
> can derive it into a B that adds that fucntionality. If I want to add more
> functionality, I can derive B into a C. But if I want to add a third bit of
> functionality D directly to A, such that D knows nothing about B or C, I
> won't be able to instantiate an object that has all three extensions, namely
> an "ABCD". It will either be an "ABC" or an "AD".
>
> One possibility would be to define the extensions B,C and D as functions and
> add those functions to A with new.instancemethod. Any other ideas on how to
> do this? E.g. is it possible to *add* base classes to a class? I could add
> the extensions by adding them as base classes to A.
>
> Thanks,
> Oliver
>
>
>[/color]
I do a template class using a function:
def B(baseclass):
class B(baseclass):
def f(self, x, y):
# do stuff
super(B, self).f(x, y)
return B
def C(baseclass):
class C(baseclass):
def f(self, x, y):
# do stuff
super(C, self).f(x, y)
return C
extendedA = C(B(A))
extendedA.f(3,4)
I think you can find recipes like this in the Python cookbook...
David | | | | re: multiple extensions to a class
Humpty Dumpty wrote:
[color=blue]
>One possibility would be to define the extensions B,C and D as functions and
>add those functions to A with new.instancemethod. Any other ideas on how to
>do this? E.g. is it possible to *add* base classes to a class? I could add
>the extensions by adding them as base classes to A.
>
>[/color]
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. (It's hard to say whether you'd be better off making B and
C separate decorators, or whether to subclass C from B -- depends on
your specific application.)
Jeff Shannon
Technician/Programmer
Credit International | | | | re: multiple extensions to a class
Jeff Shannon wrote:[color=blue]
> Humpty Dumpty wrote:
>[color=green]
>> One possibility would be to define the extensions B,C and D as
>> functions and
>> add those functions to A with new.instancemethod. Any other ideas on
>> how to
>> do this? E.g. is it possible to *add* base classes to a class? I could
>> add
>> the extensions by adding them as base classes to A.
>>
>>[/color]
>
> 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. (It's hard to say whether you'd be better off making B and
> C separate decorators, or whether to subclass C from B -- depends on
> your specific application.)
>[/color]
The advantage of Python here is that you don't need to subclass one from
the other - just make a clear definition of the methods you expect, and
then have a system where you call methods on a list of listening classes...
David | | | | re: multiple extensions to a class
"Humpty Dumpty" <oliver.schoenborn@utoronto.ca> wrote in message news:<dVnHc.35189$WM5.1797482@news20.bellglobal.co m>...[color=blue]
> Hello, I'm experimenting with different ways of extending a class (for a
> plug-ins framework for a GUI) with more than one extension when some of
> these extensions need to collaborate, but others mustn't know about each
> other.
>
> I.e., if I have a class A, and I want to add a block of functionality, I
> can derive it into a B that adds that fucntionality. If I want to add more
> functionality, I can derive B into a C. But if I want to add a third bit of
> functionality D directly to A, such that D knows nothing about B or C, I
> won't be able to instantiate an object that has all three extensions, namely
> an "ABCD". It will either be an "ABC" or an "AD".
>
> One possibility would be to define the extensions B,C and D as functions and
> add those functions to A with new.instancemethod. Any other ideas on how to
> do this? E.g. is it possible to *add* base classes to a class? I could add
> the extensions by adding them as base classes to A.
>
> Thanks,
> Oliver[/color]
I am not sure about your question. It seems you want mixins. Do you want
the ability to add a plugin dynamically and add new methods to all
your objects at run-time, including previously instanced objects?
It can be done. Or maybe you want to decide the plugins to use at import
time, i.e. you want "import_with_metaclass". In this case you may
google this newgroup and look at this article: http://www-106.ibm.com/developerwork.../l-pymeta.html
(there is also a second one http://www-106.ibm.com/developerworks/library/l-pymeta2)
HTH,
Michele Simionato | | | | re: multiple extensions to a class
Humpty Dumpty wrote:
[color=blue]
> I.e., if I have a class A, and I want to add a block of functionality, I
> can derive it into a B that adds that fucntionality. If I want to add more
> functionality, I can derive B into a C. But if I want to add a third bit
> of functionality D directly to A, such that D knows nothing about B or C,
> I won't be able to instantiate an object that has all three extensions,
> namely an "ABCD". It will either be an "ABC" or an "AD".[/color]
This sounds like the following inheritance tree would be the obvious answer:
class A: pass
class B: pass
class C: pass
class D: pass
class AB(A, B): pass
class ABC(A, B, C): pass
class AD(A, D): pass
I may still be misunderstanding something...
Peter | | | | re: multiple extensions to a class
On Thu, 8 Jul 2004 23:01:52 -0400, Humpty Dumpty
<oliver.schoenborn@utoronto.ca> wrote:[color=blue]
> Hello, I'm experimenting with different ways of extending a class (for a
> plug-ins framework for a GUI) with more than one extension when some of
> these extensions need to collaborate, but others mustn't know about each
> other.
>
> I.e., if I have a class A, and I want to add a block of functionality, I
> can derive it into a B that adds that fucntionality. If I want to add more
> functionality, I can derive B into a C. But if I want to add a third bit of
> functionality D directly to A, such that D knows nothing about B or C, I
> won't be able to instantiate an object that has all three extensions, namely
> an "ABCD". It will either be an "ABC" or an "AD".
>
> One possibility would be to define the extensions B,C and D as functions and
> add those functions to A with new.instancemethod. Any other ideas on how to
> do this? E.g. is it possible to *add* base classes to a class? I could add
> the extensions by adding them as base classes to A.[/color]
maybe I'm missing something, but wouldn't a class E(ABC, AD) work?
--
John Lenton (jlenton@gmail.com) -- Random fortune:
bash: fortune: command not found | | | | re: multiple extensions to a class
From: "John Lenton" <jlenton@gmail.com>[color=blue][color=green]
> > I.e., if I have a class A, and I want to add a block of functionality,[/color][/color]
I[color=blue][color=green]
> > can derive it into a B that adds that fucntionality. If I want to add[/color][/color]
more[color=blue][color=green]
> > functionality, I can derive B into a C. But if I want to add a third bit[/color][/color]
of[color=blue][color=green]
> > functionality D directly to A, such that D knows nothing about B or C, I
> > won't be able to instantiate an object that has all three extensions,[/color][/color]
namely[color=blue][color=green]
> > an "ABCD". It will either be an "ABC" or an "AD".
> >
> > One possibility would be to define the extensions B,C and D as functions[/color][/color]
and[color=blue][color=green]
> > add those functions to A with new.instancemethod. Any other ideas on how[/color][/color]
to[color=blue][color=green]
> > do this? E.g. is it possible to *add* base classes to a class? I could[/color][/color]
add[color=blue][color=green]
> > the extensions by adding them as base classes to A.[/color]
>
> maybe I'm missing something, but wouldn't a class E(ABC, AD) work?[/color]
No because B,C and D are discovered at run-time only, ie class E can't be
known until runtime. You'd have to create a string with the code and use
exec or eval or s/t similar.
Oliver | | | | re: multiple extensions to a class
"Peter Otten" <__peter__@web.de> wrote in message
news:ccof5d$t2b$06$1@news.t-online.com...[color=blue]
> Humpty Dumpty wrote:
>[color=green]
> > I.e., if I have a class A, and I want to add a block of functionality,[/color][/color]
I[color=blue][color=green]
> > can derive it into a B that adds that fucntionality. If I want to add[/color][/color]
more[color=blue][color=green]
> > functionality, I can derive B into a C. But if I want to add a third bit
> > of functionality D directly to A, such that D knows nothing about B or[/color][/color]
C,[color=blue][color=green]
> > I won't be able to instantiate an object that has all three extensions,
> > namely an "ABCD". It will either be an "ABC" or an "AD".[/color]
>
> This sounds like the following inheritance tree would be the obvious[/color]
answer:[color=blue]
>
> class A: pass
> class B: pass
> class C: pass
> class D: pass
>
> class AB(A, B): pass
> class ABC(A, B, C): pass
> class AD(A, D): pass[/color]
Which one offers "ABCD"? Plus, as I just mentioned in a reply to another
poster in this thread, B,C and D are discovered at run-time so anything
based on class Something(derived from combination of A,B,C,D) is doomed
since derivation is not dynamic.
Oliver | | | | re: multiple extensions to a class
From: "David Fraser" <davidf@sjsoft.com>
[color=blue]
> Jeff Shannon wrote:[color=green]
> > Humpty Dumpty wrote:
> >[color=darkred]
> >> One possibility would be to define the extensions B,C and D as[/color][/color][/color]
functions and[color=blue][color=green][color=darkred]
> >> add those functions to A with new.instancemethod. Any other ideas on[/color][/color][/color]
how to[color=blue][color=green][color=darkred]
> >> do this? E.g. is it possible to *add* base classes to a class? I could[/color][/color][/color]
add[color=blue][color=green][color=darkred]
> >> the extensions by adding them as base classes to A.
> >>[/color]
> > 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.[/color][/color]
Interesting idea, could be done... how does this differ from the mixin
approach?
[color=blue][color=green]
> > (It's hard to say whether you'd be better off making B and
> > C separate decorators, or whether to subclass C from B -- depends on
> > your specific application.)[/color][/color]
I could probably create a forwarding mechanism so that if a class doesn't
understand something, it passes on the request to each decorator in a list.
Then C could just be a decorator of B, just like B is of A.
[color=blue]
> The advantage of Python here is that you don't need to subclass one from
> the other - just make a clear definition of the methods you expect, and
> then have a system where you call methods on a list of listening[/color]
classes...
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" :)
Oliver | | | | re: multiple extensions to a class
"Humpty Dumpty" <oliver.schoenborn@utoronto.ca> wrote in message news:<JqnIc.1771$RD4.334862@news20.bellglobal.com> ...[color=blue]
>
> No because B,C and D are discovered at run-time only, ie class E can't be
> known until runtime. You'd have to create a string with the code and use
> exec or eval or s/t similar.[/color]
Not at all. You can create classes at run-time with "type":
type("MyDynamicClass",bases_set_at_run_time,dict_s et_at_run_time)
Michele Simionato | | | | re: multiple extensions to a class
Humpty Dumpty wrote:
[color=blue][color=green]
>> class AB(A, B): pass
>> class ABC(A, B, C): pass
>> class AD(A, D): pass[/color]
>
> Which one offers "ABCD"? Plus, as I just mentioned in a reply to another
> poster in this thread, B,C and D are discovered at run-time so anything
> based on class Something(derived from combination of A,B,C,D) is doomed
> since derivation is not dynamic.[/color]
The idea was that the classes you would actually use are arbitrary
combinations of "partial implementation" classes that bear no inheritance
relationships.
Seems like I misunderstood your problem and you were after the technical
means to perform this combination at runtime. - Michele has just shown how
to achieve that with type().
Peter | | | | re: multiple extensions to a class
Humpty Dumpty wrote:
[color=blue]
>From: "David Fraser" <davidf@sjsoft.com>
>
>
>[color=green]
>>Jeff Shannon wrote:
>>
>>[color=darkred]
>>>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.
>>>
>>>[/color][/color]
>
>Interesting idea, could be done... how does this differ from the mixin
>approach?
>
>[/color]
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.)
[color=blue]
>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" :)
>
>[/color]
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 |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,471 network members.
|