I'm writing an event-driven GUI framework. I have several independent units of functionality such as Draggable, Highlightable, etc. Although these units of functionality are independent of each other, they do all depend on a certain base implementation that they work with. I want widget objects to be able to select different combinations of these capabilities at will. So mixins seemed like the way to go.
It seemed to me that the most natural way to implement mixins in Python is to use multiple inheritance with new-style classes. But I certainly confused myself a lot trying to do it. I think I have come up with the solution, although its late and this is pretty rushed, but I thought it would put it out there for comment. Is this the right thing to do? The lessons I learned are that, when implementing mixins using multiple inheritance: * Mixin classes should not derive from any base class (except object) * But they may assume that the classes they will be mixed in with do derive from a certain base class, so they may assume the base class is there. Here's some code showing the approach that seems to work for me: <code> class Base(object): """Base class for mixer classes. All mixin classes require the classes they are mixed in with to be instances of this class (or a subclass).""" def __init__(self,b): self.b = b # Mixin classes assume this attribute will be present class MixinBPlusOne(object): """A mixin class that implements the print_b_plus_one method.""" def __init__(self): print 'MixinBPlusOne initialising' def print_b_plus_one(self): print self.b+1 class MixinBMinusOne(object): """A mixin class that implements the print_b_minus_one method.""" def __init__(self): print 'MixinBMinusOne initialising' def print_b_minus_one(self): print self.b-1 class Mixer(Base,MixinBPlusOne,MixinBMinusOne): """A mixer class (class that inherits some mixins), this will work because it also inherits Base, which the mixins expect.""" def __init__(self,b): # I feel like I should be using super here because # I'm using new-style classes and multiple # inheritance, but the argument list of # Base.__init__ differs from those of the Mixin # classes, and this seems to work anyway. Base.__init__(self,b) MixinBPlusOne.__init__(self) MixinBMinusOne.__init__(self) class BrokenMixer(MixinBPlusOne,MixinBMinusOne): """This will not work because it does not inherit Base, which the mixins expect it to do.""" pass m = Mixer(9) m.print_b_plus_one() m.print_b_minus_one() m = BrokenMixer(9) m.print_b_plus_one() # It'll crash here. </code> It outputs this, the result I expected: MixinBPlusOne initialising MixinBMinusOne initialising 10 8 <crash!> _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor