Inheritance is one of three pillars(Encapsulation, Inheritance, and Polymorphism) in OOP. JavaScript does not support these in a language level. But you know you can create an object and add properties and methods to it. ASP.NET AJAX Library also helps that you can upgrade the constructor function to a class. Now, how about inheritance? Is it possible?
1. Prototype-based Inheritance
Every JavaScript object has a “prototype” object and you can add static properties and functions to it, so that all object can share the data or methods.
This “prototype” object is key to the inheritance in JavaScript.
2. Creating Inheritance
Let’s create a prototype-based inheritance without using ASP.NET AJAX Library.
- Define a base class
- Define a sub class
- Inherit the properties defined in the base class: Call the base class’s constructor within the sub class’s constructor; the “call()” method of the “Function” object is used.
- Inherit the properties defined in the “prototype” object of the base class: Assign the base class’s “prototype” object as a new instance of a base class
- Override methods if necessary
The key steps are (3) and (4).
Point = function () { this.x = ''; } Point.prototype = { get_point: function () { return 'x = ' + this.x; } } Point2D = function () { Point.call(this); this.y = ''; } Point2D.prototype = new Point(); Point2D.prototype.get_point = function () { return 'x = ' + this.x + ',y = ' + this.y; } var p1 = new Point(); p1.x = 5; alert(p1.get_point()); var p2 = new Point2D(); p2.x = 5; p2.y = 10; alert(p2.get_point());
3. Creating Inheritance using ASP.NET AJAX Library
It’s ok to create a inheritance chain without using the library. Now let’s find out how ASP.NET AJAX Library help us to do the same task more clearly. To set up inheritance relationship, you need to pass a base class when you create a sub class with the “registerClass()” function.
- Define a base class
- Register the base class
- Define a sub class
- Call the “initializeBase()” function in the subclass’s constructor function
- Override methods if necessary
- Register the subclass
Type.registerNamespace("MyAjax"); MyAjax.Point = function () { this.x = 0; } MyAjax.Point.prototype = { get_point: function () { return 'x = ' + this.x; } } MyAjax.Point.registerClass('MyAjax.Point'); MyAjax.Point2D = function () { MyAjax.Point2D.initializeBase(this); this.y = 0; } MyAjax.Point2D.prototype = { get_point: function () { return 'x = ' + this.x + ',y = ' + this.y; } } MyAjax.Point2D.registerClass('MyAjax.Point2D', MyAjax.Point); var p1 = new MyAjax.Point(); p1.x = 5; alert(p1.get_point()); var p2 = new MyAjax.Point2D(); p2.x = 5; p2.y = 10; alert(p2.get_point());
Rather than call the base class’s constructor directly, you need to call the “initializeBase(this)” method. It takes care of sharing all properties by walking the inheritance chain.
4. Passing Argument.
It is pretty common to pass a initial value to constructors. To pass arguments to the constructor of a base class, you have to pass them as an array to the “initializeBase()” method.
Let’s modify the previous example.
Type.registerNamespace("MyAjax"); MyAjax.Point = function (_x) { this.x = _x; } MyAjax.Point.prototype = { get_point: function () { return 'x = ' + this.x; } } MyAjax.Point.registerClass('MyAjax.Point'); MyAjax.Point2D = function (_x, _y) { MyAjax.Point2D.initializeBase(this, [_x]); this.y = _y; } MyAjax.Point2D.prototype = { get_point: function () { return 'x = ' + this.x + ',y = ' + this.y; } } MyAjax.Point2D.registerClass('MyAjax.Point2D', MyAjax.Point); var p1 = new MyAjax.Point(5); alert(p1.get_point()); var p2 = new MyAjax.Point2D(5,10); alert(p2.get_point());
5. Overriding Methods
Overriding a method is pretty easy. You can just redifine the method again as we already have seen. One remaining question is how can you call a base method in the sub class once the method is replaced.
The syntax is like this:
<Fully Qualified sub class Name>.callBaseMethod(this, “method name”, [parameters, …] );
MyAjax.Point2D.prototype = { get_point: function () { var xPoint = MyAjax.Point2D.callBaseMethod(this, 'get_point'); return xPoint + ',y = ' + this.y; } }
6, Inheritance Type Reflection
The “inheritsFrom()” and the “isInstanceOfType()” methods are used to check type reflections.
... MyAjax.Point.registerClass('MyAjax.Point'); ... MyAjax.Point2D.registerClass('MyAjax.Point2D', MyAjax.Point); if (MyAjax.Point.isInstanceOfType(p1)) alert('p1 is an instance of MyAjax.Point'); // true if (MyAjax.Point2D.isInstanceOfType(p1)) alert('p1 is an instance of MyAjax.Point2D'); // false if (MyAjax.Point.isInstanceOfType(p2)) alert('p2 is an instance of MyAjax.Point'); // true if (MyAjax.Point2D.isInstanceOfType(p2)) alert('p2 is an instance of MyAjax.Point2D'); // true
Note that p2 is also an instance of a base class.
if (MyAjax.Point.inheritsFrom(MyAjax.Point2D)) alert('MyAjax.Point inherits from MyAjax.Point2D'); // false if (MyAjax.Point2D.inheritsFrom(MyAjax.Point)) alert('MyAjax.Point2D inherits from MyAjax.Point'); // true