tags:

views:

1356

answers:

8

In "Programming Python", Mark Lutz mentions "mixins". I'm from a C/C++/C# background, and I've not heard the term before. What is a mixin?

Reading between the lines of this example (which I've linked to, 'cause it's quite long) I'm presuming it's a case of using multiple inheritance to extend a class as opposed to 'proper' subclassing. Is this right? Why would I want to do that rather than put the new functionality into a subclass? For that matter, why would a mixin/multiple inheritance approach be better than using composition?

Edit: Thank you for some really good answers, I've upvoted quite a few. I've not accepted a final answer yet, because although I feel I have a decent idea about what mixins can be used for, I'd really like to get my head around exactly what a mixin is - specifically, what separates a mixin from multiple inheritance? Is it just a matter of semantics?

+2  A: 

I could type up a long reply, but this article is quite good and answers your question:

http://www.linuxjournal.com/node/4540/print

levand
It's funny, but I asked this question because I read that article and didn't think that it explained the concept!
Dan
+5  A: 

There's a short series of articles (Part 1, Part 2) on Artima that talk about mixins from a Python perspective. Don't be deceived by the "Considered Harmful" title. They give of a good overview of what mixins are and when it is or is not a good idea to use them.

Kamil Kisiel
+13  A: 

First, you should note that mixins only exist in multiple-inheritance languages. You can't do a mixin in Java or C#.

Basically, a mixin is a stand-alone base type that provides limited functionality and polymorphic resonance for a child class. If you're thinking in C#, think of an interface that you don't have to actually implement because it's already implemented; you just inherit from it and benefit from its functionality.

Mixins are typically narrow in scope and not meant to be extended.

[edit -- as to why:]

I suppose I should address why, since you asked. The big benefit is that you don't have to do it yourself over and over again. In C#, the biggest place where a mixin could benefit might be from the Disposal pattern. Whenever you implement IDisposable, you almost always want to follow the same pattern, but you end up writing and re-writing the same basic code with minor variations. If there were an extendable Disposal mixin, you could save yourself a lot of extra typing.

[edit 2 -- to answer your other questions]

What separates a mixin from multiple inheritance? Is it just a matter of semantics?

Yes. The difference between a mixin and standard multiple inheritance is just a matter of semantics; a class that has multiple inheritance might utilize a mixin as part of that multiple inheritance.

The point of a mixin is to create a type that can be "mixed in" to any other type via inheritance without affecting the inheriting type while still offering some beneficial functionality for that type.

Again, think of an interface that is already implemented.

I personally don't use mixins since I develop primarily in a language that doesn't support them, so I'm having a really difficult time coming up with a decent example that will just supply that "ahah!" moment for you. But I'll try again. I'm going to use an example that's contrived -- most languages already provide the feature in some way or another -- but that will, hopefully, explain how mixins are supposed to be created and used. Here goes:

Suppose you have a type that you want to be able to serialize to and from XML. You want the type to provide a "ToXML" method that returns a string containing an XML fragment with the data values of the type, and a "FromXML" that allows the type to reconstruct its data values from an XML fragment in a string. Again, this is a contrived example, so perhaps you use a file stream, or an XML Writer class from your language's runtime library... whatever. The point is that you want to serialize your object to XML and get a new object back from XML.

The other important point in this example is that you want to do this in a generic way. You don't want to have to implement a "ToXML" and "FromXML" method for every type that you want to serialize, you want some generic means of ensuring that your type will do this and it just works. You want code reuse.

If your language supported it, you could create the XmlSerializable mixin to do your work for you. This type would implement the ToXML and the FromXML methods. It would, using some mechanism that's not important to the example, be capable of gathering all the necessary data from any type that it's mixed in with to build the XML fragment returned by ToXML and it would be equally capable of restoring that data when FromXML is called.

And.. that's it. To use it, you would have any type that needs to be serialized to XML inherit from XmlSerializable. Whenever you needed to serialize or deserialize that type, you would simply call ToXML or FromXML. In fact, since XmlSerializable is a fully-fledged type and polymorphic, you could conceivably build a document serializer that doesn't know anything about your original type, accepting only, say, an array of XmlSerializable types.

Now imagine using this scenario for other things, like creating a mixin that ensures that every class that mixes it in logs every method call, or a mixin that provides transactionality to the type that mixes it in. The list can go on and on.

If you just think of a mixin as a small base type designed to add a small amount of functionality to a type without otherwise affecting that type, then you're golden.

Hopefully. :)

Randolpho
Hey, do you like that phrase "polymorphic resonance"? Made it up myself. I think. Maybe I heard it in physics somewhere...
Randolpho
I disagree slightly on your first sentence. Ruby is a single-inheritance language and mixins are the way to add methods to a given class w/o inherite from another class.
Keltia
Holy crap, you pinged me over a pedantic distinction? Pretty harsh, man.
Randolpho
@Randolpho -- lighten up -- it's a conversation.
S.Lott
@Keltia: I think that mixin's are -- by definition -- multiple-inheritance. In the Ruby case, they're a monkeypatch (or something else) not a proper mixin. The Ruby folks may call it a mixin, but it's a different kind of thing.
S.Lott
@S.Lott: But, but... my rep, man! :D
Randolpho
@Randolpho: your rep will take care of itself (which sounds so lame coming from me... but... it's true). Rep is earned in obscure ways. I still get upvotes from answers posted months ago.
S.Lott
@S.Lott: I was just joking. It's a conversation, lighten up. :)
Randolpho
+1 good summary of the pros of using a mixin.
Carl Meyer
"First, you should note that mixins only exist in multiple-inheritance languages. You can't do a mixin in Java or C#."C# 3.0 added extension methods which do allow you to "sort of" use mixins in C#. See http://stackoverflow.com/questions/783312/interface-extension-mixin-vs-base-class
dss539
@dss539 I think C# extension methods pretty much fall under the case of Ruby mixins as discussed above -- a patch to make something *seem* like a mixin, without actually *being* a mixin.
Randolpho
With the XML example, isn't it possible to just have a class called XMLSerializer that the client class has a reference to?
helloworlder
@helloworlder: Yes, you could. That wouldn't be a mixin, however. Again, I was trying to use a contrived example of a mixin, not trying to specify best-practice for XML serialization.
Randolpho
+4  A: 

Maybe an example from ruby can help:

You can include the mixin Comparable and define one function "<=>(other)", the mixin provides all those functions:

<(other)
>(other)
==(other)
<=(other)
>=(other)
between?(other)

It does this by invoking <=>(other) and giving back the right result.

"instance <=> other" returns 0 if both objects are equal, less than 0 if instance is bigger than other and more than 0 if other is bigger.

Georg
+5  A: 

I'd advise against mix-ins in new Python code, if you can find any other way around it (such as composition-instead-of-inheritance, or just monkey-patching methods into your own classes) that isn't much more effort.

In old-style classes you could use mix-ins as a way of grabbing a few methods from another class. But in the new-style world everything, even the mix-in, inherits from object. That means that any use of multiple inheritance naturally introduces MRO issues.

There are ways to make multiple-inheritance MRO work in Python, most notably the super() function, but it means you have to do your whole class hierarchy using super(), and it's considerably more difficult to understand the flow of control.

bobince
+4  A: 

Perhaps a couple of examples will help.

If you're building a class and you want it to act like a dictionary, you can define all the various __ __ methods necessary. But that's a bit of a pain. As an alternative, you can just define a few, and inherit (in addition to any other inheritance) from UserDict.DictMixin (moved to collections.DictMixin in py3k). This will have the effect of automatically defining all the rest of the dictionary api.

A second example: the GUI toolkit wxPython allows you to make list controls with multiple columns (like, say, the file display in Windows Explorer). By default, these lists are fairly basic. You can add additional functionality, such as the ability to sort the list by a particular column by clicking on the column header, by inheriting from ListCtrl and adding appropriate mixins.

John Fouhy
+7  A: 

I'd really like to get my head around exactly what a mixin is - specifically, what separates a mixin from multiple inheritance?

A mixin is a special kind of MI. There are two main situations where mixins are used:

  1. You want to provide a lot of optional features for a class.
  2. You want to use one particular feature in a lot of different classes.

For an example of number one, consider werkzeug's request and response system (link now 404, sadly). I can make a plain old request object by saying:

from werkzeug import BaseRequest

class Request(BaseRequest):
    pass

If I want to add accept header support, I would make that

from werkzeug import BaseRequest, AcceptMixin

class Request(BaseRequest, AcceptMixin):
    pass

If I wanted to make a request object that supports accept headers, etags, authentication, and user agent support, I could do this:

from werkzeug import BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthorizationMixin

class Request(BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthorizationMixin):
    pass

The difference is subtle, but in the above examples, the mixin classes weren't made to stand on their own. In more traditional MI, The AuthenticationMixin (for example) would probably be something more like Authenticator. That is, the class would probably be designed to stand on its own.

Jason Baker
A: 

It's not a Python example but in the D programing language uses the term mixin is uaed to refer to a construct used much the same way; adding a pile of stuff to a class.

In D (which by the way doesn't do MI) this is done by inserting a template (think syntactically aware and safe macros and you will be close) into a scope. This allows for a single line of code in a class, struct, function, module or whatever to expand to any number of declarations.

BCS
Mixin is a general term, used in D, Ruby, etc. According to Wikipedia, they originated in old school lisp systems, and were first documented in 1983: http://en.wikipedia.org/wiki/Flavors_%28computer_science%29#cite_note-0
Lee B
@Lee: ok, so it's not new to D. @whoever down voted: Why?
BCS
Hmm. I downvoted it, because I took your "It's not python but D..." to be an attempt to explain incorrectly that mixins belong to the D language and not python (or others). I see now that you probably just meant that you couldn't talk about mixins in python, but could compare with D. Apologies, my mistake. My vote can't be changed now, or I'd do so.
Lee B
Ahh. OK. Edited to avoid that in the future.
BCS