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 jsclass
have some special methods for modifying the methods they contain.
The following 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()
.
If you want to create aliases for methods that already exist, use the alias()
method. The new alias goes on the left-hand-side, the existing method name on
the right.
Animal.alias({ talk: 'speak', rest: 'sleep' });
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 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.