Python Design Patterns - composition vs. inheritance

Chris Mellon arkanes at gmail.com
Thu Nov 15 17:45:23 EST 2007


On Nov 15, 2007 2:37 PM, Diez B. Roggisch <deets at nospam.web.de> wrote:
>
> > 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. 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?
>
> Yes. Of course there are other ways, establishing the connection later,
> and of course making the Owner know her pets. But your unidirectional,
> ctor-passed implementation is sensible.
>
> > 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? Ideally, should I be writing
> > getattr() methods so I can do pet.address instead of
> > pet.owner.address? Should I be doing the same with owner's methods
> > like I did with get_foo()?
>
> No, that's certainly not a good idea. And I'm under the impression you
> misunderstood something there in the original lecture/explanation.
>
> The reason is simple: by adding these methods, you essentially extend
> Pet's knowledge as a class to what only its owner has to know. Which
> makes no sense. Why should pets know about addresses? Or cars? Or
> anything else that belongs to the owner only.
>
> Of course there are just reasons to create such delegation methods - if
> for example the property/method is of general interest to the Pet, but
> implemented by means of the owner. But I've got difficulties even to
> imagine such thing, at least in your actual example.
>

An example might be something like pet.has_foodbowl, which is
implemented as self.owner.has_foodbowl_for(self). If you've got pets
with more than one owner, it might be any(owner.has_foodbowl_for(self)
for owner in self.owners) - certainly a candidate for an easy accessor
in the Pet class.

This is more an example of API convenience than it is any sort of
general OO or type theory concept. Note that any time you do this sort
of reverse binding you're codifying assumptions about your object
model (by which I mean domain objects, rather than your inheritance
hierarchy) into your code.

I don't worry to much about is-a or has-a or any sort of strict class
hierarchy or type system. I view inheritance, in Python, as a way of
inheriting implementation and I do it when I want some other classes
implementation and not otherwise. In other languages (not C++ family,
but ML family) I think much more in terms of types and type systems,
but in Python I stay pragmatic and flexible.



More information about the Python-list mailing list