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