19

It seems that in all class-based or prototypal OOP languages, mixins are either an afterthought or a secondary feature. However, to me it looks like traditional inheritance is just a specific case of using a single mixin.

I am assuming this is because of historical reasons and familiarity, but maybe there is something else? Problems with sharing encapsulated state safely?

Den
  • 4,827
  • 2
  • 32
  • 48
  • 2
    Traits in Scala? Also, I don't think this really applies to languages such as Eiffel or C++ that allow multiple inheritance, where you can model any "abstract" class to be a "mixin". – SBI Nov 02 '15 at 12:10
  • 1
    @gnat - the accepted answer there focuses on prototypal OOP "Prototypical inheritance is simple." - my question is more agnostic. – Den Nov 02 '15 at 12:18
  • I feel it doesn't necessarily need to be a duplicate. However, there needs to be a distinction between language feature and modelling technique, such as using abstract or even concrete classes with few or a single method as a mixin. – SBI Nov 02 '15 at 12:18
  • @SBI traits are different http://stackoverflow.com/questions/925609/mixins-vs-traits – Den Nov 02 '15 at 12:18
  • That's exactly what I'm playing at in my second comment ;) – SBI Nov 02 '15 at 12:19
  • It should also be noted that most class-based OOP languages need to support some level of backwards compatibility (to languages that don't have mixins). – Telastyn Nov 02 '15 at 14:30
  • One could argue that Golang is such. – Lee Daniel Crocker Nov 02 '15 at 16:53
  • 2
    The question supposes that one needs a reason to not spend dozens of programmer-years making a new language whose compelling benefit is not that it solves some problem, but that it is built around a particular philosophy. New languages are insanely expensive; you need a reason to expend that effort, not a reason to *not* expend that effort! – Eric Lippert Nov 02 '15 at 17:39
  • @EricLippert This is really not the way I wanted my question to be read (I am open to better wording). I am just wondering why "hardcode" one scenario and then patch it instead of making it flexible to begin with. Are mixins such a novel concept? – Den Nov 02 '15 at 17:47
  • 1
    But *every* design process entails deciding what features will be flexible and which will be foundational. Flexibility is extremely expensive across many dimensions of language design; adding more flexibility often means deprioritizing things like performance or understandability. – Eric Lippert Nov 02 '15 at 17:51
  • @EricLippert this could be an additional answer to this question - "understandability" is what I was thinking about when I wrote "familiarity". – Den Nov 02 '15 at 17:57
  • @Den: That's not quite what I meant; by "understandability" I mean "can I look at a fragment of the code and understand its meaning without global knowledge of the program". Some languages allow you to, say, dynamically change the member lookup rules, so looking at "foo.bar" does not let me know that a member bar is being accessed on an object foo. Highly flexible languages can prioritize developer convenience over maintainer convenience; whether that is an acceptable tradeoff is an important design consideration. – Eric Lippert Nov 02 '15 at 17:59
  • My opinion: It's because traditionally, class-based languages have not had functions as first-class values, and without that mixins just don't work (assuming you don't consider things like Go's struct embedding to be a kind of mixin). In languages like Javascript, mixins are perfectly normal, and arguably more straightforward than other types of inheritance. – Ixrec Nov 02 '15 at 21:05
  • D has template mixins. In D, structs can't inherit from a class so the only way to reuse code for them is via a mixin. – Átila Neves Nov 07 '15 at 12:10

1 Answers1

32

The seminal paper on mixins is Gilad Bracha's PhD thesis The Programming Language Jigsaw: Mixins, Modularity and Multiple Inheritance.

It has answers to all of your questions, like

  • Why not make a language with mixin-only inheritance?

    Jigsaw is such a language, as is Newspeak, Bracha's current language

  • However, to me it looks like traditional inheritance is just a specific case of using a single mixin.

Indeed, mixin inheritance subsumes all classical forms of single (class-based) inheritance (Simula-/Smalltalk-style inheritance as well as Beta-style prefixing), as well as multiple class-based inheritance with linearization (CLOS, C++, Python, …)

You may want to have a look at Newspeak. Don't be fooled by the fact that it has "classes". They are actually mixins. The Jigsaw paper describes how classes can be elevated to mixins, and that is exactly how it works in Newspeak.

Basically, a mixin is a class that doesn't know its superclass. Therefore, it can appear at multiple places in the inheritance tree. (Note that this is not multiple inheritance! It is, in fact, in some sense exactly the opposite or dual: in multiple inheritance, a class appears at a single place with multiple superclasses, in mixin inheritance, a class appears at multiple places with a single superclass.)

In Newspeak, OO is taken to the extreme: everything is a message send ("virtual method/function call" in Javanese/C++). Even superclass lookup. So, when you declare a class Sub as a subclass of Super, the superclass of Sub is not stored inside some pointer in the internal implementation of Sub, no, whenever you need the superclass (e.g. during message dispatch (virtual method/function lookup/dispatch in Javanese/C++)), the runtime interprets Super as the name of a method to call which returns a class. However, it is not known at runtime which class it returns. In fact, it might return a different class every time! Therefore, classes in Newspeak don't know their superclass, which is the/a definition of a mixin.

Note that in a prototype-based language, the idea of having a dedicated mixin makes no sense. The whole point of a prototype-based language is that there is only one kind of "things" (objects) as opposed to two kinds of "things" (objects and classes, objects and traits, objects and mixins, …). They can be used as a Design Pattern, of course. That's how they were originally invented, after all, in the Flavors object system for Lisp, which had classes with multiple inheritance, but the classes were often used in a peculiar way, which they called mixins (and from which the object system got its name).

Jörg W Mittag
  • 101,921
  • 24
  • 218
  • 318
  • 4
    For those without postscript viewers: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.51.662&rep=rep1&type=pdf – Jules Nov 02 '15 at 17:51
  • 3
    Is there any consensus or general opinion about whether this is an effective way of organizing code? Does it really help anything, or is it just a neat idea that doesn't play out very practically? – jpmc26 Nov 02 '15 at 18:04
  • Excellent answer and that paper is fantastic. I disagree about the last paragraph though, prototype based languages can still have mixins as sugar for copying all properties over from one object for another. JavaScript had an `Object.mixin` at a point (which was renamed `.assign`) and has dedicated mixin syntax in the upcoming version (assuming that makes the cut). You can "mixin" two objects without a second "thing", it's not exactly Bracha's mixins in Jigsaw but it's the same concept. – Benjamin Gruenbaum Nov 02 '15 at 19:29
  • In what sense is the superclass a superclass, if it's not known? Why even use that terminology at all? – Kevin Krumwiede Nov 02 '15 at 22:10
  • 1
    @KevinKrumwiede: In Java, as well as all other blass-based OO languages, a class doesn't know its subclasses. Yet, we can still talk about subclasses in a sensible manner. Why should superclasses be any different? When a mixin is mixed into a class, the mixin becomes the class's new superclass and the old superclass becomes the mixin's superclass. IOW: the mixin is inserted into the class hierarchy between the mixed-into class an its superclass. It works like any other class. It has a superclass. However, since it can appear multiple times, each time with a different superclass, it cannot … – Jörg W Mittag Nov 03 '15 at 00:31
  • 1
    … make any assumptions about its superclass. – Jörg W Mittag Nov 03 '15 at 00:31