Skip to content


Multiple inheritance? Mixins? #452

TrevorBurnham opened this Issue · 36 comments

I'm loving the extends keyword, but in the course of developing a complex project, I really wish I could give a class functionality from multiple sources. Obviously I could do this by extending the prototype manually, but it feels like a hack to mix the extends syntax with JavaScript-style prototype manipulation.

For my purposes, it would be great to be able to say

class A extends Foo, Bar

but I realize that multiple inheritance is a huge headache, so Ruby-style mixins or Scala-style traits would probably be a better solution. The Scala syntax would be especially nice for CoffeeScript:

class A extends Foo with Bar

Obviously with is already a keyword, but its meaning in this syntax is unambiguous.

Of course, this is something that a standard library could do, but it would be much clearer to have something like the above syntax rather than something like

class A extends foo
   # properties...

lib.mixin A, bar

What does everyone else think?


Yes, mixins - I'm missing them too.


So. JavaScript inheritance of properties through prototypes is only for single inheritance. You can have chains pointing back as long as you like, but there's only one prototype per-object.

Any "mixin" functionality would be limited to what can be accomplished at runtime through helper functions, as mentioned above. It would be a blind copy of properties onto the object or prototype, not a true inclusion, where subsequent changes to the module would affect the mixed-in objects. For this reason, I don't think that it's in the domain of CoffeeScript. Is there a concrete proposal for what you'd like it to compile into?


I would like

class A extends Foo with Bar, Baz

to copy the properties from the Bar and Baz prototypes over to A. Naturally, I wouldn't be able to use super if I overrode a Bar or Baz function, because that could be ambiguous. It would still be quite useful, though, for adding certain kinds of functionality to multiple classes. It's syntactic sugar, plus folks coming from Ruby probably expect some kind of mixin functionality in the language.

class A extends Foo merge Bar, Baz



Closing this one as a wontfix, here's why:

The idea with CoffeeScript classes is to expose the common pattern of use of JavaScript's prototype chains in a convenient way -- not to mimic classes from Ruby or another language. If you'd like to include methods from an external module into a class you have a number of options: you can delegate to the class, manually copy methods over, or use a helper function like Prototype's extend.

It's an orthogonal issue to classes ... you should equally well be able to "mixin" functions into a vanilla object, which is something that an extend function does.


Mootools solves this using an Implements property. A Class in Mootools can extend only one other, but can implement as many as required. A common example is:

Button: new Class {
  Extends: Control,
  Implements: [Options, Events]
cancel: new Button()
cancel.addEvent 'click', ( -> false)

This is very powerful and I use it quite a lot in my code. Options and Events are so common that every UI class must have them.

I personally think Coffee should have a second think about allowing this kind of construct.

class Button extends Control implements Options, Events

From the docs:


The Class that this class will extend. i.e. proper inheritance


Implements is similar to Extends, except that it adopts properties from one or more other classes without inheritance. Useful when implementing a default set of properties in multiple Classes.


We can reopen it if someone cooks up a patch they'd like to propose.


If we had inline anonymous classes, it would be possible to implement mixins in user code while keeping them at the top of the class definition:

implementing: (mixins..., classReference) ->
    for mixin in mixins
        for key, value of mixin::
            (classReference::)[key]: value

Button: implementing Options, Events, class 
    doSomething: ->

cancel: new Button()
cancel.addEvent 'click', ( -> false)

...although a class defined this way could not have a subclass containing super calls, since it would not be bound to a name at compile-time.


+1 for some kind of mixin functionality. It seems awkward and un-coffee to create a class and then copy functions to the prototype after the definition. That functionality feels like it belongs in the class definition.



class Options
  options: {}
  setOptions: (o) ->
    for own key, value of o
      @options[key] = value

class Button extends Control implements Options, Events





Sorry, folks, but +1s aren't terribly helpful without a specific implementation strategy you'd like to propose. Multiple inheritance simply does not exist in JavaScript -- you have a single __proto__ property, which points at a single parent object.


@jashkenas Thanks you for you response and I'm sorry for my noisy comment...
Simple function copying like Backbone.Events is a good starting point for me.
For name conflicts, I prefer just throwing error to avoid accidental override.


You can have a longer prototype chain, or am I doing something stupid?

x = function(){};
x.prototype = { x: 1 };
y = function(){};
y.prototype = new x();
y.prototype.y = 2;
z = function(){ this.z = 3; };
z.prototype = new y();
z.prototype.z = 3;
a = function(){};
a.prototype = new z();
a.prototype.a = 4;

console.log(new a)

x.prototype.b = 5;

console.log(new a);

@ricardobeat: Yes, an object can have a long prototype chain -- but each object in the chain will inherit from another object in the chain. If you instead have 2 existing objects, a and b, which don't inherit from each other, you cannot make object c inherit from both of them.


As a workaround, you can copy functions into a class on initialize with jQuery to get snapshot mixins using something like the following:

initialize: ->
  jQuery.extend this, YourHelper.prototype

Not without limitation, but lets you "choose composition over inheritance".

UPDATE: Read the mixin section on, previous link was broken, thanks @countable :)


hm, that link on Mixins in the last post is dead now, and this issue is closed but it comes up first in Google for "coffeescript mixins", so incase anyone else ends up here, I'll note the Spine framework has support which you can easily steal as an alternative to the @captainpete workaround.

class Module
  @include: (obj) ->
    throw('include(obj) requires obj') unless obj
    for key, value of obj when key not in moduleKeywords
      @::[key] = value

    included = obj.included
    included.apply(this) if included

and then to use it

helper = 
    my_helper_fn: -> 'i'm helping'

class MyClass extends Module
     @include helper
Function::use = (argv...) ->
  for cl in argv
    for key, value of cl::

class A
  a: -> 
class B 
  b: -> 
class C
  @use A,B
  c: ->

i = new C
console.log i



I agree that one shouldn't mess with the inheritance chain, but I do think that coffee-script should provide the functionality that Spine does, namely including other classes. Let extends do what it does, but also let me @include EventEmitter :-)

I hope you'll consider this. Thanks


I totally agree with @jashkenas . Coffeescript should not, and not ever, mimic the (useful?) constructs of other languages. Some seem to confuse the intention of Coffescript with libraries such as Prototype, MooTools, jQuery, Spine Go write a library, or something.



Also, this is 2 years old.


Yes @Nami-Doc, but the issue still holds relevance, don't you think? I stumbled upon this thread today, investigating multiple inheritance in coffescript and javascript. It seems to me the only way to achieve multiple inheritance in Javascript is to be rather explicit ...


Yes, that's why I linked coco's solution.


ty @Nami-Doc .


For me, it's not about other language constructs, but the Object Oriented paradigm, reusability and a way to code. Yes, we can live without it, but, something like Interfaces, that just have methods, or just signatures could be useful.

Why not just put methods of "interface C" into a "class B" that extends "class A" and, if it isn't implemented, throws an exception?

 for(var m in implemented){
     myClass[m] = function(){
          throw new Error("Method " + m + " has not been implemented");

Then, we will have

 class B extends A implements C, D
      csMethod : ->
      dsMethod : ->

Or just make a mixin modificator, making new objects of C and D inside B's creator function and mixes its methods into B

  class B extends A mixin C, D

Hey folks, I got Mixins in CoffeeScript ;)


Mixins still could be useful for specifying behaviours which do not require managing their own "state" — in the context of Backbone I can think of a ViewBehaviour which can provide some methods for View for turning el into "contenteditable" element.

I still do think that mixins should be implemented by mangling a prototype chain, so they easily can be stacked up into complex behaviours. I propose the following implementation as a draft:

class Base
  @with: (mixins...) ->
    for mixin in mixins

      cur = mixin
      protos = loop
        proto = Object.getPrototypeOf(cur)
        break if proto == Object.prototype
        cur = proto


      newProto = Object.getPrototypeOf(this.prototype)

      for proto in protos
        newProto = extend Object.create(newProto), {constructor: newProto.constructor}, proto

      this.__super__ = Object.getPrototypeOf(newProto)
      this.prototype = newProto

# example

Mixin =
  a: ->
    console.log 'Mixin'

class A extends Base
  @with Mixin

  a: ->
    console.log 'A'

a = new A

# prints 'A'
# prints 'Mixin'

So basically what I think could be useful as a language support — include or with keyword instead of static method call (for backward compatibility) and corresponding super references inside non-methods.

class B extends A with Mixin

I support closing this bug. Here's how I get mixins:

mixOf = (base, mixins...) ->
  class Mixed extends base
  for mixin in mixins by -1
    for name, method of mixin::
      Mixed::[name] = method


class A extends mixOf Foo, Bar

Yes, it makes the prototype chain longer and calling Foo methods from A is microscopically slower, but it has almost exactly the semantics I'd expect¹, and it's 6 simple lines. In fact, it's hard for me to imagine what I'd want any of the above-proposed syntactic sugar to compile into, if not this.

¹ I mean:

  • yes: "super" from A methods
  • yes: no python-style method-resolution-order magic from "super" in Bar methods (that would be multiple inheritance, not mixins)
  • no: methods that Bar inherits from a superclass (technically, mixins should have this; but pragmatically, it's good that this doesn't, because it discourages mixins as anything but simple one-offs.)
  • no: changes to mixin are not reflected in A (again, technically bad but pragmatically good)
yi commented

I found Ruby's acts_as pattern is really handy when doing Ruby on Rails work. I were long to bring it to JS. Inspired by your comments, I've put a npm module to provide a similar "composition over inheritance" way in coffee. And it can also check who-looks-like-who for duck typing


I think you should post that on the mailing list/irc, that possibly can interest some people. (I'd like to reduce noise in old and closed issue, however :).)

@vendethiel vendethiel reopened this
@vendethiel vendethiel closed this
yi commented

understand, thank you :smile:


You can take a look at CoffeeClasskit.

I made it with an eye on Ruby's modules system. It uses Object.defineProperty, __proto__ and other modern features, so it wouldn't work in old browsers. But works fine in node.


For some may be interesting this variant:


I think as ES6 and proxies are coming, this should be reconsidered.



Just wanted to bring awareness to a little module I made, which implements multiple inheritance:

The interesting thing about this implementation is that, unlike the mixin-based approaches discussed here so far, it supports cooperative multiple inheritance, in a way similar to how Python does it. It has some drawbacks, so I'm unsure it's appropriate for the core language, but it should help pythonistas to import their beloved patterns.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.