[Tutor] subclassing across multiple modules

Kent Johnson kent37 at tds.net
Fri Mar 18 13:35:13 CET 2005


Brian van den Broek wrote:
> Kent Johnson said unto the world upon 2005-03-17 20:44:

>> The multiple inheritance from MyNode and Toolkit.NodeX is a smell. I 
>> guess you do this because you want to override methods of Toolkit.Node 
>> as well as Toolkit.NodeX, or add methods to both MyNode1 and MyNode2? 
>> I would look for another way to do this, maybe using some kind of 
>> helper class to hold some common functions?
> 
> 
> 
> The adding methods rationale. I never instantiate Node, instead I use it 
> for behaviour common to Node1 and Node2. Toolkit.py gives specialized 
> methods to both Node1 and Node2. I need MyNode1 and MyNode2 (the 
> Application.py versions) to have all the powers of the Toolkit.Node1 and 
> Node2 classes, plus some new powers in common, and some new powers 
> defined separately. That is the sort of thing I had understood multiple 
> inheritance to be for -- but my understanding is about as shaky as an 
> addict in withdrawal :-)
> 
> Are you suggesting the multiple inheritance is always a smell?

No. Some people would agree with that - e.g. the creators of Java - but I have seen many times where
MI is useful. Usually it is to combine a primary base class with a mixin - a class that adds
functionality orthogonal to that of the base class, or that modifies a carefully chosen set of base
class methods.
http://c2.com/cgi/wiki?MultipleInheritanceIsNotEvil
http://c2.com/cgi/wiki?MixIn

For example in a GUI toolkit you might have an Observable add-in that gives a class means to
remember and broadcast to listeners. In the Python library there are SocketServer mixins that create
a threaded server.

BUT there are some clear gotchas to MI. They mostly arise when you inherit from classes that
themselves have a common base class. The "diamond" pattern is the usual example:

class A:
   ..

class B(A):
   ..

class C(A):
   ..

class D(B, C):
   ..

Now you can have all kinds of fun (i.e. subtle bugs and confusion) if A, B, C and D have methods in
common and if they want to call the methods of their base classes. One of the changes is new-style
classes (the addition of super() and a change to the "method resolution order") was made to address
some deficiencies in how old-style classes handle this situation.

So, calling this a code smell is probably not the right term. It's more like a red warning light and
klaxon :-) You just don't want to do this without understanding the issues.

See http://www.python.org/doc/2.2.3/whatsnew/sect-rellinks.html#SECTION000330000000000000000 and PEP
253 for details or google "diamond multiple inheritance"


> I'll google, but my only grasp of the meaning of "helper class" is what 
> comes from intuition.

For example, instead of subclassing Toolkit.Node, could you define the extra methods in another
class. Then your NodeX subclasses can inherit from Toolkit.NodeX and NodeHelper. e.g.

class MyNodeHelper:
   def doSomethingSpecial(self):
     # does something with a Toolkit.Node

class MyNode1(Toolkit.Node1, MyNodeHelper):
   ..

This is an example of a mixin class.

Kent




More information about the Tutor mailing list