The YUI Global Object: Create Class Hierarchies with extend
JavaScript supports the notion of class hierarchies. As in other object-oriented languages, you can create generic classes, then create specialized subclasses that add or override functionality of the superclass.
Click the "Show Inheritance" button to do some evaluation of the created object.
var chicken = new Chicken();
Using extend
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.
Creating a class hierarchy
In this example, we create a class Bird
then create a subclass Chicken
.
Bird = function (name) { this.name = name; }; Bird.prototype.flighted = true; // Default for all Birds Bird.prototype.isFlighted = function () { return this.flighted }; Bird.prototype.getName = function () { return this.name }; Chicken = function (name) { // Chain the constructors Chicken.superclass.constructor.call(this, name); }; // Chickens are birds Y.extend(Chicken, Bird); // Define the Chicken prototype methods/members Chicken.prototype.flighted = false; // Override default for all Chickens
Bird = function (name) { this.name = name; }; Bird.prototype.flighted = true; // Default for all Birds Bird.prototype.isFlighted = function () { return this.flighted }; Bird.prototype.getName = function () { return this.name }; Chicken = function (name) { // Chain the constructors Chicken.superclass.constructor.call(this, name); }; // Chickens are birds Y.extend(Chicken, Bird); // Define the Chicken prototype methods/members Chicken.prototype.flighted = false; // Override default for all Chickens
instanceof
many classes
Unlike classes composed with augmentation, subclasses created with extend
are also
considered instances of their superclass and all classes higher up the
inheritance tree.
We'll create an instance of Chicken
and run some instanceof
and method tests against it.
showInheritance = function () { var chicken = new Chicken('Little'), results = Y.one('#demo'); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Object) ? "<p>chicken IS an instance of Object.</p>" : "<p>chicken IS NOT an instance of Object.</p>")); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Bird) ? "<p>chicken IS an instance of Bird.</p>" : "<p>chicken IS NOT an instance of Bird.</p>")); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Chicken) ? "<p>chicken IS an instance of Chicken.</p>" : "<p>chicken IS NOT an instance of Chicken.</p>")); // Chicken instances inherit Bird methods and members results.set('innerHTML', results.get('innerHTML') + ((chicken.isFlighted()) ? "<p>chicken CAN fly.</p>" : "<p>chicken CAN NOT fly.</p>")); results.set('innerHTML', results.get('innerHTML') + "<p>chicken's name is " + chicken.getName() + ".</p>"); } Y.on('click', showInheritance, '#demo_btn');
showInheritance = function () { var chicken = new Chicken('Little'), results = Y.one('#demo'); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Object) ? "<p>chicken IS an instance of Object.</p>" : "<p>chicken IS NOT an instance of Object.</p>")); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Bird) ? "<p>chicken IS an instance of Bird.</p>" : "<p>chicken IS NOT an instance of Bird.</p>")); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Chicken) ? "<p>chicken IS an instance of Chicken.</p>" : "<p>chicken IS NOT an instance of Chicken.</p>")); // Chicken instances inherit Bird methods and members results.set('innerHTML', results.get('innerHTML') + ((chicken.isFlighted()) ? "<p>chicken CAN fly.</p>" : "<p>chicken CAN NOT fly.</p>")); results.set('innerHTML', results.get('innerHTML') + "<p>chicken's name is " + chicken.getName() + ".</p>"); } Y.on('click', showInheritance, '#demo_btn');
Other architecture strategies
Take a look at augment
and mix
for different strategies of managing your code structure.
Full Source
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 Bird = function (name) { this.name = name; }; Bird.prototype.flighted = true; // Default for all Birds Bird.prototype.isFlighted = function () { return this.flighted }; Bird.prototype.getName = function () { return this.name }; Chicken = function (name) { // Chain the constructors Chicken.superclass.constructor.call(this, name); }; // Chickens are birds Y.extend(Chicken, Bird); // Define the Chicken prototype methods/members Chicken.prototype.flighted = false; // Override default for all Chickens showInheritance = function () { var chicken = new Chicken('Little'), results = Y.one('#demo'); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Object) ? "<p>chicken IS an instance of Object.</p>" : "<p>chicken IS NOT an instance of Object.</p>")); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Bird) ? "<p>chicken IS an instance of Y.example.Bird.</p>" : "<p>chicken IS NOT an instance of Y.example.Bird.</p>")); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Chicken) ? "<p>chicken IS an instance of Y.example.Chicken.</p>" : "<p>chicken IS NOT an instance of Y.example.Chicken.</p>")); // Chicken instances inherit Bird methods and members results.set('innerHTML', results.get('innerHTML') + ((chicken.isFlighted()) ? "<p>chicken CAN fly.</p>" : "<p>chicken CAN NOT fly.</p>")); results.set('innerHTML', results.get('innerHTML') + "<p>chicken's name is " + chicken.getName() + ".</p>"); } Y.on('click', showInheritance, '#demo_btn'); });
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 Bird = function (name) { this.name = name; }; Bird.prototype.flighted = true; // Default for all Birds Bird.prototype.isFlighted = function () { return this.flighted }; Bird.prototype.getName = function () { return this.name }; Chicken = function (name) { // Chain the constructors Chicken.superclass.constructor.call(this, name); }; // Chickens are birds Y.extend(Chicken, Bird); // Define the Chicken prototype methods/members Chicken.prototype.flighted = false; // Override default for all Chickens showInheritance = function () { var chicken = new Chicken('Little'), results = Y.one('#demo'); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Object) ? "<p>chicken IS an instance of Object.</p>" : "<p>chicken IS NOT an instance of Object.</p>")); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Bird) ? "<p>chicken IS an instance of Y.example.Bird.</p>" : "<p>chicken IS NOT an instance of Y.example.Bird.</p>")); results.set('innerHTML', results.get('innerHTML') + ((chicken instanceof Chicken) ? "<p>chicken IS an instance of Y.example.Chicken.</p>" : "<p>chicken IS NOT an instance of Y.example.Chicken.</p>")); // Chicken instances inherit Bird methods and members results.set('innerHTML', results.get('innerHTML') + ((chicken.isFlighted()) ? "<p>chicken CAN fly.</p>" : "<p>chicken CAN NOT fly.</p>")); results.set('innerHTML', results.get('innerHTML') + "<p>chicken's name is " + chicken.getName() + ".</p>"); } Y.on('click', showInheritance, '#demo_btn'); });