classes (was Re: Same again please for OOP)

Alex Martelli aleaxit at yahoo.com
Sun Dec 24 20:53:02 CET 2000


"Roy Smith" <roy at panix.com> wrote in message
news:roy-E5B925.13324224122000 at news.panix.com...
> "Alex Martelli" <aleaxit at yahoo.com> wrote:
> > For example, suppose our program will need to model CD's.  A CD
> > object has several attributes -- depending on our purposes, we may
> > want to model some appropriate subset of them; for example, a
> > "title", a "price" in Euros, and a sequence of "tracks" (each of which
> > has its own attributes, say a "title" and a "duration" in seconds).
>
> That's good as far as it goes, but I think you missed the real power of
> classes, which is subclassing.

I disagree that subclassing is 'the real power' -- it's just one handy
way, one of many, of reusing some code.  You may be confusing
subclassing with *polymorphism*, which IS indeed _awesomely_
powerful... but, in Python, need not have anything to do with the
'subclassing' implementation technique (an easy confusion to make
if coming from languages, such as C++ and Eiffel, which almost
equate polymorphism with subclassing... Java, which singles out
interfaces as its preferred road to polymorphism, may lead to some
more conceptual clarity about this distinction!).


'As far as it goes' were 324 lines, and I couldn't do justice to the
_behavior_ concept at all within those confines, let alone the key
case of _polymorphic_ behavior.  Particularly because ideal Python
style, IMHO, needs _much_ clarity about the state/behavior
distinction, one which is often missing, witness...:

> The mp3 class might return a URL for its location() method, and the CD
> or Vinyl classes might return a string, "Third shelf from the bottom,

Looks like a typical case of state mismodeled as behavior.  Why should
'location' be a method -- what does it *DO*?!  It doesnt _do_ anything;
rather, it's an 'accessor' for a part of the object's state.  A typical
'implementation' would be, say:
    def location(self):
        return self.the_location
where we can't give that part-of-state its 'normal' name, which would
be just 'location', since the method's name preempts it.  In the crucial
spirit of "do the simplest thing that can possibly work", modeling state
as state (attributes) is often best in Python -- with __getattr__ and
__setattr__ in reserve if we later refactor it in more sophisticated ways
(to meet some specific application need) and want to insulate client
code from the effects of such changes.

Hardly a suitable showcase for polymorphism -- or, actually, for
behavior *at all*.

One can do better, of course.  But, didactically, I think that it's much
better to start by ensuring a good understanding of class instances
as handy holders of *state*, with 'behavior' initially limited to that
connected with initialization, before moving on to more general issues
of behavior, and, from there, to polymorphism (and to subclassing in
various uses -- the purely utilitarian use of mixin inheritance is, I
believe, a suitable introduction, _before_ proceeding with subtler and
more refined issues related to the interplay of inheritance and
polymorphism; it's nice that Python lends itself so cleanly to a
presentation of these issues as separate -- in fact, it's part of what
makes it such an ideal language for _teaching_ OO, quite apart from
the fact that it's also ideal for _doing_ it:-).

And I wouldn't present such instruction in posts of more than a
few hundreds lines at a time, because even the simplest way to
present things still needs the reader to digest each step properly,
before moving on...


Alex






More information about the Python-list mailing list