Modifying existing classes and modules
Just like in Ruby, classes and modules are open for modification at any time, so
you can add and change methods in existing classes. All classes and modules in JS.Class
have two special methods for modifying the methods they contain. The below is written
to apply to modifying classes, but it applies equally to modifying modules – classes are
just modules that can be instantiated.
The first of these methods is called define(). This adds a single named method to the
class/module. If you’re modifying a class, the method instantly becomes available
in instances of the class, and in its subclasses.
Animal.define('sleep', function() {
return this.name + ' is sleeping';
});
rex.sleep()
// -> "Rex is sleeping"
Note that if the class already has a method with the same name as the one you’re defining,
the old method will be overwritten. Methods in parent classes and in mixins can be accessed
using callSuper().
The other option available to you is to use include(). This method has a couple of roles;
if you supply a Module, the module is mixed into the class and becomes
part of its inheritance tree. If you supply any other type of object, the methods from the
object are copied into the class itself, overwriting any pre-existing methods with similar names.
// Replace Dog's speak method (#1)
Dog.include({
speak: function(stuff) {
return this.callSuper('lots of ' + stuff) + '!';
}
});
rex.speak('cats')
// -> "My name is Rex and I like lots of cats!"
// Mix in a module, altering the class's ancestry
// callSuper() in Dog#speak will now call this method
var Speaker = new JS.Module({
speak: function(stuff) {
return 'I can talk about ' + stuff + '!';
}
});
Dog.include(Speaker);
rex.speak('cats')
// -> "I can talk about lots of cats!!"
Notice how including Speaker does not overwrite the speak method in the Dog class
(marked #1 above). That method is defined in Dog and will persist until overwritten
directly in the Dog class. Speaker merely injects another method called speak into
the inheritance chain for the Dog class. For more information, refer to the explanation
of Ruby’s method lookup algorithm.