On Wed, 03 Apr 2013 15:04:51 +0100, andrea crotti wrote: > I have some classes that have shared behaviours, for example in our > scenario an object can be "visited", where something that is visitable > would have some behaviour like
[snip mixins] By the way, it's a common convention to name mixin classes as "SpamMixin". > So now I'm not sure how to use it though. > One way would be multiple subclasses > > class MyObjectBase(object): > pass > > class MyObj(MyObjectBase, Visitable): > pass > > for example. What's the purpose of MyObjectBase? Either your example is too simple, or it actually has no purpose, and you should simply write: class MyObj(object, VisitableMixin): # code goes here instead of having one extra layer in the inheritance hierarchy. > This solution is probably easy, but at the same time disturbing because > MyObjectBase is semantically quite different from Visitable, so > subclassing from both seems wrong.. Not really. From what you describe, this seems to be exactly the use-case for mixins. Yes, mixins are by definition somewhat of an abuse of Object- Oriented concepts. Mixins don't so much represent a "type of thing" as a convenient bundle of encapsulated behaviour and/or state. E.g. MyObj represents some sort of "MyObj thing" (or at least it *should*, if your OO classes are well-planned), but Visitable(Mixin) does not represent a thing at all. But here's a way to look at it to justify the concept of mixins. Think of regular classes and subclasses as representing trees of descent, like biological groups: Animal -> Mammal -> Rodent -> Porcupine Animal -> Monotreme -> Echidna Then mixins represent convergent evolution of some trait: Animal -> Mammal -> Rodent + QuillsMixin -> Porcupine Animal -> Monotreme + QuillsMixin -> Echidna > The other solution (which is what is partially done now) is to use > another class attribute: > > class ObjectWithMixin(CouchObject): > MIXINS = [Visitable] > > and then do all the smart things needed: > - at object construction time > - when setting attributes and so on.. > > This solution is more complicated to implement but maybe is more > flexible and more "correct", what do you think? I think that's worse. You seem to have *almost* stumbled onto the design pattern known as "composition" or "delegation", only not quite. Normal class-based design models a "is-a" relationship. "Lassie is a Dog", so we would do: lassie = Dog() Composition models a "has-a" relationship. For example, both cars and boats have engines, so we might be tempted to use a mixin: class Car(EngineMixin): pass class Boat(EngineMixin): pass which isn't an awful solution. But a conceptually cleaner solution might be to do this: class Car: def __init__(self): self.engine = Engine() def go(self): print "Fasten your seat belt" self.engine.start() self.handbrake = False self.change_gear("drive") self.accelerate() class Boat: def __init__(self): self.engine = Engine() def go(self): ... and then both cars and boats can *delegate* behaviour to the engine object. So, if you think of "Visitable" as a gadget that can be strapped onto your MyObj as a component, then composition is probably a better design. But if you think of "Visitable" as a mere collection of behaviour and state, then a mixin is probably a better design. -- Steven -- http://mail.python.org/mailman/listinfo/python-list