Python Design Patterns - composition vs. inheritance
Bruno Desthuilliers
bruno.42.desthuilliers at wtf.websiteburo.oops.com
Fri Nov 16 12:52:14 EST 2007
snewman18 at gmail.com a écrit :
> In learning about design patterns, I've seen discussion about using
> inheritance when an object's relationship to another object is 'is-a'
> and composition when the relationship is 'has-a'.
wrt/ inheritance, it only makes sens with declarative static type
systems where polymorphic dispatch depends on subclassing (so
inheritance is used for both implementation and subtyping). In the
context of a dynamic type system, inheritance is only for implementation
reuse, ie given the following class definitions :
class Foo(object):
def bar(self):
return 42
class Baaz(object):
def bar(self):
return 84
Baaz actually 'is a' (proper subtype of) Foo (and vice-versa).
>
> Since this is all new and I'm still learning, I was hoping someone can
> give me some pointers on best practices on applying these ideas. If my
> logic is incorrect on anything, please don't hesitate to tell me where
> I'm wrong - I'm completely open to any help offered.
>
> As a very simplified example, if I had two classes, Pet and Owner, it
> seems that I would not have Pet inherit from Owner, since a pet 'has
> an' owner, but not 'is an' owner.
Both (I mean 'has a' and 'is a') are not necessary exclusive.
> If this is correct, does my code
> below reflect this? I passed the owner object into the pet object's
> constructor - is this the right way to do it?
Here again, it depends on the lifetime cycles of both objects. Look for
the difference between composition and aggregation. And it of course
depends on the problem you're trying to solve - there's no such thing as
an 'absolute' model.
> Also, I've seen talk that ideally you shouldn't have too many "dots"
> in your method calls, instead using delegates to the methods and
> attributes. Can anyone elaborate on this?
"should", "should not", laws and golden rules... Indeed, it's usually
better to respect encapsulation.
> Ideally, should I be writing
> getattr() methods so I can do pet.address instead of
> pet.owner.address?
What's the use of pet.address ? Is really 'adress' a responsability of
'Pet' ?
> Should I be doing the same with owner's methods
> like I did with get_foo()?
Python's methods actually are attributes, so you don't (technically)
need a distinct scheme for methods - __getattr__ will work as well.
__getattr__ is fine when you really have a generic delegation (look for
the Proxy pattern for an example). Else (ie, you decide that, for this
given problem, 'address' is really a responsability of Pet), you might
be better defining an explicit 'address' attribute in Pet - preferably
using a computed attribute (either a property object or a custom
descriptor).
Anyway, the simplest your design and implementation, the better.
My 2 cents...
More information about the Python-list
mailing list