Monday, June 16th, 2008

Enhanced Class Inheritance with JavaScriptMVC

Category: JavaScript, Programming

<>p>Brian Moschel from the JavaScriptMVC project wrote in to tell us about their recent efforts extending John Resig’s earlier Simple Class Inheritance work.

In case you missed it, John’s blog talked about his efforts to take the best of the many efforts to simulate classical inheritance in JavaScript and reduce them to a simple, easy-to-use piece of stand-alone JavaScript. Here’s an example of the syntax he settled on:

javascript
< view plain text >
  1. var Person = Class.extend({
  2.   init: function(isDancing){
  3.     this.dancing = isDancing;
  4.   },
  5.   dance: function(){
  6.     return this.dancing;
  7.   }
  8. });
  9.  
  10. var Ninja = Person.extend({
  11.   init: function(){
  12.     this._super( false );
  13.   },
  14.   dance: function(){
  15.     // Call the inherited version of dance()
  16.     return this._super();
  17.   },
  18.   swingSword: function(){
  19.     return true;
  20.   }
  21. });
  22.  
  23. var p = new Person(true);
  24. p.dance(); // => true
  25.  
  26. var n = new Ninja();
  27. n.dance(); // => false
  28. n.swingSword(); // => true
  29.  
  30. // Should all be true
  31. p instanceof Person && p instanceof Class &&
  32. n instanceof Ninja && n instanceof Person && n instanceof Class

The JavaScriptMVC guys built on top of his work to add:

  • Class level inheritance: Easily reuse functionality by inheriting class methods and using superclass methods the same way as instance methods
  • Class initialization callbacks: Setup your classes and keep track of subclasses with callback functions invoked once during class initialization
  • Introspection: Allow classes to behave differently based on the name of the class, similar to ActiveRecord
  • Access to the instance’s class and superclass: Write code that directly accesses class methods and objects from instance methods even when you don’t know the name of the class

Their stuff will be available as a plugin to JavaScriptMVC at some point in the future, but is available now as standalone JavaScript.

Here’s a code sample of these new features at work:

javascript
< view plain text >
  1. Class.extend(‘monster’,
  2.   // class methods
  3.   {
  4.     find: function(name){
  5.       return this.creatures[name];
  6.     },
  7.     // called whenever Monster is subclassed
  8.     extended: function(Class){
  9.       this.types.push(Class.className);
  10.     },
  11.     types: [],
  12.     creatures: {}
  13.   },
  14.   // prototype methods
  15.   {
  16.   // constructor
  17.   init: function(name){
  18.     this.name = name;
  19.     this.life = 100;
  20.     this.attack_stength = 20;
  21.     this.Class.creatures[name] = this;
  22.   },
  23.   attack: function(creature){
  24.     creature.life -= this.attack_stength;
  25.   }
  26. });
  27.  
  28. Monster.extend(’sea_monster’);
  29. Monster.extend(‘dragon’,{
  30.   find: function(name){
  31.     var found = this._super(name);
  32.     // Dragons’ spirits are raised when they feel wanted
  33.     found.life+=10;
  34.     return found;
  35.   }
  36. },{
  37.   init: function(name){
  38.     // call the inherited version of init()
  39.     this._super(name);
  40.     this.attack_stength = 50;
  41.   },
  42.   attack: function(creature){
  43.     // dragons hurt themselves a bit when they attack
  44.     this.life -= 5;
  45.     // call the inherited version of attack
  46.     this._super(creature);
  47.   }
  48. })
  49.  
  50. Monster.types; // => [’sea_monster’,'dragon’]
  51. var h = new Monster(‘hydra’);
  52. var a = new Dragon(‘albi’);
  53. a.attack_stength; // 50
  54. a.Class.className; // ‘dragon’
  55. a.attack(h); // h.life = 50, a.life = 95
  56. var d = Dragon.find(‘albi’); // returns albi instance, d.life = 105

Related Content:

1 Comment »

Comments feed TrackBack URI

Thanks for posting Ben. Do you have an email address anywhere? I didn’t see it on your blog or Ajaxian.

A couple points worth mentioning:

- To use this with Prototype, you’ll probably have to change Class to MVCClass, or something else, since Prototype uses Class in the global namespace. This is only an issue with the standalone script, not the plugin.
- This script is compressible because superclass methods are assigned as a function attached to “this”, rather than an argument (Prototype’s method).

Comment by moschel — June 16, 2008

Leave a comment

You must be logged in to post a comment.