The YUI Global Object: Compose Classes of Objects with augment
In this example, a class has been created then augmented with
EventTarget
to provide custom event functionality.
Click the Send button to send the instance of the new class a request.
Using augment
Instantiate YUI
<!-- include yui --> <script type="text/javascript" src="../../build/yui/yui.js"></script> YUI().use("node", function(Y) { // This method is in the 'oop' module. Since we require 'node' // for this example, and 'node' requires 'oop', the 'oop' module // will be loaded automatically.
<!-- include yui --> <script type="text/javascript" src="../../build/yui/yui.js"></script> YUI().use("node", function(Y) { // This method is in the 'oop' module. Since we require 'node' // for this example, and 'node' requires 'oop', the 'oop' module // will be loaded automatically.
The example: Any class can be an EventTarget
This example creates a custom class, then augments it with
EventTarget
(functionality included in the YUI Event Utility). Using the
packaged functionality of EventTarget
, the code for
Foo
is able to focus on the functionality unique to its
purpose.
YUI().use("node", function(Y) { // This method is in the 'oop' module. Since we require 'node' // for this example, and 'node' requires 'oop', the 'oop' module // will be loaded automatically. var Foo = function() { /* code specific to Foo */ this.publish('interestingMoment'); }; Foo.prototype.doSomething = function() { var eventData = {}; // -- do something interesting, add results to eventData -- eventData.statusText = 'bar'; // notify the subscribers, passing the event data this.fire('interestingMoment', eventData); } Y.augment(Foo, Y.EventTarget); var foo = new Foo(); // add some event listeners foo.on('interestingMoment', function (data) { var p = Y.one('#demo_p1'); p.set('innerHTML', 'I was notified of an interesting moment: ' + data.statusText); }); foo.on('interestingMoment', function (data) { var p = Y.one('#demo_p2'); p.set('innerHTML', 'I was also notified of an interesting moment: ' + data.statusText); }); Y.on('click', function() { foo.doSomething(); }, '#demo'); });
YUI().use("node", function(Y) { // This method is in the 'oop' module. Since we require 'node' // for this example, and 'node' requires 'oop', the 'oop' module // will be loaded automatically. var Foo = function() { /* code specific to Foo */ this.publish('interestingMoment'); }; Foo.prototype.doSomething = function() { var eventData = {}; // -- do something interesting, add results to eventData -- eventData.statusText = 'bar'; // notify the subscribers, passing the event data this.fire('interestingMoment', eventData); } Y.augment(Foo, Y.EventTarget); var foo = new Foo(); // add some event listeners foo.on('interestingMoment', function (data) { var p = Y.one('#demo_p1'); p.set('innerHTML', 'I was notified of an interesting moment: ' + data.statusText); }); foo.on('interestingMoment', function (data) { var p = Y.one('#demo_p2'); p.set('innerHTML', 'I was also notified of an interesting moment: ' + data.statusText); }); Y.on('click', function() { foo.doSomething(); }, '#demo'); });
Composition, not inheritance
If Foo
were a part of a class hierarchy, it would be improper
to include EventTarget
in the inheritance chain, because its custom event
functionality is not an intrinsic characteristic but rather an ancillary, generic
capability that many classes share.
Unlike extend
ed classes, the relationship between a class and
the classes augmenting it is not an indication of type hierarchy. The intent
of augment
is to aid in extracting nonessential behaviors or
behaviors shared by many classes, allowing for a composition-style class
architecture.
This may appear similar to multiple inheritance, but it's not.
augment
simply adds the public methods and members from one class
prototype to another class prototype. Instances of the augmented class will
not pass instanceof
tests for the class(es) which augmented
it.
YUI().use('oop', function(Y) { function Foo() {} Foo.prototype.doSomething = function () { /* something */ }; function Bar() {} Y.augment(Bar, Foo); var b = new Bar(); if (b instanceof Bar) {} // true if (b instanceof Foo) {} // FALSE });
YUI().use('oop', function(Y) { function Foo() {} Foo.prototype.doSomething = function () { /* something */ }; function Bar() {} Y.augment(Bar, Foo); var b = new Bar(); if (b instanceof Bar) {} // true if (b instanceof Foo) {} // FALSE });