Forwardable
What was it the Gang of Four
said? Prefer delegation. Delegation is the act of getting the receiver of a
method call to respond by simply passing that call along to some other object.
Forwardable
, a port of Ruby’s Forwardable
module, allows you to
easily define instance methods that do just that.
// In the browser JS.require('JS.Forwardable', function(Forwardable) { ... }); // In CommonJS var Forwardable = require('jsclass/src/forward').Forwardable;
Let’s say you have a class that wraps a collection of objects, which it stores as an array in one of its instance properties. You might implement some methods for manipulating the array through the class’ own interface:
var RecordCollection = new Class({ initialize: function() { this.records = []; }, push: function(record) { return this.records.push(record); }, shift: function() { return this.records.shift(); } });
Instead, you can extend
the class with Forwardable
, then use
defineDelegators()
to create the methods. defineDelegators
takes the name
of the instance property to delegate calls to as the first argument, and the
names of the delegated methods as the other arguments:
var RecordCollection = new Class({ extend: Forwardable, initialize: function() { this.records = []; } }); RecordCollection.defineDelegators('records', 'push', 'shift'); var recs = new RecordCollection(); recs.push('The White Stripes - Icky Thump'); recs.push('Battles - Mirrored'); recs.shift() // -> "The White Stripes - Icky Thump"
If you need to define extra class methods, you need to change the notation slightly:
var RecordCollection = new Class({ extend: [Forwardable, { // class methods go here }], initialize: function() { this.records = []; } });
If you want to give the delegating method a different name, use the
defineDelegator()
(singular) method instead:
// Add an instance method called 'add' that calls records.push RecordCollection.defineDelegator('records', 'push', 'add');