#77 ✓invalid
Kit Goncharov

Classes should inherit from mixins

Reported by Kit Goncharov | June 28th, 2010 @ 01:19 PM

In Prototype and the current FuseJS API, mixins are statically added (via Object.extend) as class methods, instead of inherited and added to the prototype chain. This introduces a particularly nasty gotcha: classes that include a mixin won't reflect any changes or updates to it:

var mixin = {
  "myAwesomeMethod": function(){
    console.log("Howdy!");
  }
};

var Greeter = fuse.Class({
  "greet": function(){
    this.myAwesomeMethod();
  }
}, mixin);

var greeter = new Greeter();
greeter.greet(); //=> "Howdy!"

mixin.myAwesomeMethod = function(){
  console.log("Privet!");
};

//Class doesn't inherit the redefined method!
greeter.greet(); //=> "Howdy!"

Although we may not want to change this behavior due to backward-compatibility issues, I think it's rather unintuitive. It's also interesting to note that Prototype (which emulates a Ruby-like API for JavaScript) deviates from Ruby's behavior:

#Define our mixin (Ruby modules are roughly analogous to JS namespaces)
module Mixin
  #Mixin method
  def my_awesome_method
    puts "Howdy!"
  end
end

#Define our class
class Greeter
  #Include the mixin with our awesome method
  include Mixin
  #Class/instance method
  def greet
    my_awesome_method
  end
end

#Instantiate a `Greeter`
greeter = Greeter.new
greeter.greet # => "Howdy!"

module Mixin
  #Redefine our mixin method
  def my_awesome_method
    puts "Privet!"
  end
end

#Class inherits the redefined method
greeter.greet # => "Privet!"

What do you guys think? Should we update the class API so that all classes automatically inherit from mixins as well?

Comments and changes to this ticket

  • Kit Goncharov

    Kit Goncharov June 28th, 2010 @ 01:34 PM

    A possible disadvantage of doing this is that we could easily end up with a long prototype chain, especially with multiple mixins and a superclass...

  • Radoslav Stankov

    Radoslav Stankov June 29th, 2010 @ 03:57 AM

    This could be useful (At least in Ruby is useful). The way ruby handles it is adding "something" like ghost classes which point to the mixin. In js we could use the same strategy.

    I'm not sure if this could be done in performance wise ( I could be wrong ). I think I have seen something build whit inherit mixis here - http://jsclass.jcoglan.com, but for every mixin object is actually a class.

  • John-David Dalton

    John-David Dalton September 2nd, 2010 @ 05:50 PM

    I didn't think of mixins like that. In fact I made them so they couldn't be used in a way to work with inheritance, (I have checks that stop it).

  • John-David Dalton

    John-David Dalton September 2nd, 2010 @ 05:53 PM

    FuseJS Class API

    var SomeClass = fuse.Class(superclass, plugins, mixins, statics);
    
    SomeClass.addMixins({ ... });
    
  • John-David Dalton

    John-David Dalton September 2nd, 2010 @ 05:57 PM

    Making them update when changed would require some kind of wrapper around the source method that then checks the real method:

    
    //...
     'someMethod': function() {
       return mixin.someMethod.apply(mixin, arguments);
      }
    //...
    
  • John-David Dalton

    John-David Dalton September 12th, 2010 @ 01:12 AM

    • Milestone cleared.
    • Tag set to enhancement
  • Kit Goncharov

    Kit Goncharov February 28th, 2011 @ 10:15 PM

    • State changed from “new” to “invalid”
    • Milestone order changed from “5” to “0”

    The general consensus seems to be in favor of keeping the existing Class API due to performance concerns and compatibility with the Prototype API. Closing as invalid.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

JavaScript frameworks share similar features and functionality such as DOM manipulation, event registration, and CSS selector engines. FuseJS attempts to incorporate the strengths of these frameworks into one stable, efficient, and optimized core JavaScript framework.

Pages