Composition instead of inheritance
pavlovevidence at gmail.com
Fri Apr 29 19:54:57 EDT 2011
On Friday, April 29, 2011 2:44:56 PM UTC-7, Ian wrote:
> On Fri, Apr 29, 2011 at 3:09 PM, Carl Banks
> > Here is my advice on mixins:
> > Mixins should almost always be listed first in the bases. (The only exception is to work around a technicality. Otherwise mixins go first.)
> > If a mixin defines __init__, it should always accept self, *args and **kwargs (and no other arguments), and pass those on to super().__init__. Same deal with any other function that different sister classes might define in varied ways (such as __call__).
> Really, *any* class that uses super().__init__ should take its
> arguments and pass them along in this manner.
If you are programming defensively for any possible scenario, you might try this (and you'd still fail).
In the real world, certain classes might have more or less probability to be used in a multiple inheritance situations, and programmer needs to weigh the probability of that versus the loss of readability. For me, except when I'm designing a class specifically to participate in MI (such as a mixin), readability wins.
> > A mixin should not accept arguments in __init__. Instead, it should burden the derived class to accept arguments on its behalf, and set attributes before calling super().__init__, which the mixin can access.
> Ugh. This breaks encapsulation, since if I ever need to add an
> optional argument, I have to add handling for that argument to every
> derived class that uses that mixin. The mixin should be able to
> accept new optional arguments without the derived classes needing to
> know about them.
Well, encapsulation means nothing to me; if it did I'd be using Java.
If you merely mean DRY, then I'd say this doesn't necessarily add to it. The derived class has a responsibility one way or another to get the mixin whatever initializers it needs. Whether it does that with __init__ args or through attributes it still has to do it. Since attributes are more versatile than arguments, and since it's messy to use arguments in MI situations, using attributes is the superior method.
More information about the Python-list