[Tutor] Usefulness of classes and necessity of inheriting classes

Dominik George nik at naturalnet.de
Mon Nov 25 12:12:17 CET 2013


Hi Reuben,

> Question no 1:
> ----------------------
> I would like to know why do we actually inherit classes? What would be the
> benefit of inheriting?

I think this is not the classical explanation of this, but when teaching
programming to my students, I make a very great deal of the following:

All things programming (even all things to do with computers) are about
agreements (dt. Abmachungen) and promises (dt. Versprechen). Protocols
are agreements about the communication between programs (or devices),
and a programming language is an agreement about communication between a
programmer and the machine. A program, or an interface, then, is an
agreement between the user and the programmer and his machine.

The important thing is that, as is to be expected from the kids I teach
towards their teachers, friends and family, if the agreement is
fulfilled by both sides, everything will work out well.

The machine gives us a promies: if we feed it with certain binary
operations, it will do a certain thing, and exactly this one thing
(unless it has a bug).

The Python interpreter, or its developers, gives us a promise: if we
feed it with certain lines/blocks of code, it will do exactly as asked.
If it doesn't, most likely we broke the agreement in some way or another
(unless the interpreter or the machine udner it has a bug).

Now, you could see a class as a promies to both the interpreter and
users of your class (if you use it in a library): A certain class has
certain attributes and methods, and this is a promise.

It follows, that if a class inherits from another class, then this class
will keep the promise made by the base class as well - it will (at
least) have the interface the base class is known to have.

Obviously, a developer could break this promise by manipulating stuff in
the inheriting class in an unexpected way, but that's not our fault then
nor is it Python's or the machine's fault ;).

Now, normally, you extend a class (inherit from it) when you want your
own class to basically behave the same way the base class does, and
expose more or less the same interface. Maybe you even do not want to
change the internal behaviour, but only add a tiny thing.

My experience in classroom teaching has shown that thinking of
programming and CS as making keeping promises helps a lot.

> If possible, a practical example would be of great help

A practical example, as in code - an example that has a practical use is
hard to give. But I'll try anyway:

  class Display():
      """" This class can put pixels on a monochrome display """

      def __init__(self):
          """ Do setup stuff for the display """
          pass

      def put(self, pos):
          """ Puts a pixel at an (x, y) pos
          pass

      def clear(self, pos):
          """ Clears a pixel at an (x, y) pos """
          pass

  class ColorDisplay(Display):
      """ This class behaves just like the Display class,
          but can control colour. """

      # The setup stuff is copied/inherited from the base

      def put(self, pos, colour=None):
          """ This method overrides the base method, but calls it
              in case the user does not use colour, so our interface
              is universal """

          if not colour:
              return Display.put(self, pos)

          # do colourful magic stuff here


You see that both classes can be used in exactly the same manner, but
the second one has been extended by an optional colour attribute in the
put method.

From this example, you can conclude that the inheritance was chosen to
avoid code duplication, and to sign the promise that the interfaces are
somewhat compatible.

> Question no 2:
> ----------------------
> 
> Why would I ever use a class? I understand this is strange question
> 
> May be an example to make me understand would be useful.
> 
> Or may be answering the question should be rephrased as "Why not use
> modules instead of classes?"

Because you cannot (well you can, but not without turning right into a
zombie) make a copy of a module. When you instantiate a class, you get a
copy of its attributes in something like a dictionary (exposed in a
different way) and it is independent of the other copies.

The only reasonable thing you do with a module is importing it. With
that, you get a copy of its *name* - mind you, modules and importing are
all about names and namespaces, no more no less.

So imagine a module named spam, with these contents:

  bacon = 5
  eggs  = 7

Now, do something like this:

  import spam as spam1
  import spam as spam2

This is completely valid, but you only get two names pointing to the
exact same thing:

  spam1.bacon = 10
  print(spam2.bacon)

This will give 10. You most likely did not want that ;).

What you *can* do is write simple functions in a module that expect a
certain (promised) data structure as input and manipulates it in a
(promised) way, like so:

  def grow_a_human(human):
      human['length'] += 10

  my_human = {'length': 120, 'weight': 25}

You can iamgine how to put that in classes. And as a matter of fact,
classes in Python aren't so much different from that. The attributes in
a class are in a very dict-like thing, and the class methods are called
on it. Maybe you wondered about the self argument in every class method:

  def dosomething(self):
      pass

Now having this in a class called Spam, and having that instantiated as
mySpam, Python's magic more or less does nothing more than

  Spam.dosomething(mySpam)

when you call

  mySpam.dosomething()


So, classes and object orientation are mostly just another way to look
at things. It allows for tighter contracts (agreements, promises) and
for a more natural model. Class methods do something with the object
they belong to, so the object is "self-managed". In the example above: a
human is not grown by something outside it, but it grows by its own body
chemics and power.

So, modelling things is a bit clearer with classes.

There are a lot more traditional explanations, but I hope this is enough
for the tutors list ;).

HTH,
Nik

-- 
* concerning Mozilla code leaking assertion failures to tty without D-BUS *
<mirabilos> That means, D-BUS is a tool that makes software look better
            than it actually is.

PGP-Fingerprint: 3C9D 54A4 7575 C026 FB17  FD26 B79A 3C16 A0C4 F296
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 905 bytes
Desc: Digital signature
URL: <http://mail.python.org/pipermail/tutor/attachments/20131125/8d9920a2/attachment.sig>


More information about the Tutor mailing list