Classing{js} Tutorial

Inheritance

A Quick Review on The Concept of Inheritance

Inheritance is a mechanism for code reuse. The concept is similar to inheritance in living things : a child 'inherits' the behaviour and the traits of its parent, and in object oriented programming : a child class 'inherits' the behaviour (methods) and the traits (attributes and proprties) of its parent class.

Class inheritance follows the following rules :

How Inheritance is done ?

In Classing{js}, inheritance is done using classing.Class.Extends as in the following code :

var Child = classing.Class.Extends(/* Parent's Reference */)({
	/* The Defintion of The Class */
});
				

Here's an example of a class named Rectangle inherting from a class named Shape:

var Shape = classing.Class({
	protected : {
		height: null,
		width : null,
	},
	public : {
		Height : {
			get : function() {return this.height;},
			set : function(value) {this.height = value;}
		},
		Width : {
			get : function() {return this.width;},
			set : function(value) {this.width = value;}
		},
		Area : function() {
			return "Not Implemented";
		}
	}
});

var Rectangle = classing.Class.Extends(Shape)({
	public : {
		Area : function() {
			return this.width*this.height;
		}
	}
});
				

Notice that the Rectangle class overrides the Area method to calculate the area of the rectangle instead of returning "Not Implemented".

According to the second rule of inheritance mentioned above, any object of the Rectangle class will be able to access any of the two protected inherited attributes height and width inside its proprties and methods (like in the overriden method Area). And the two public inherited proprties Height and Width can be accessed from within or outside the class from the object.

The 'base' Keyword

The base keyword gives you access to the parent object within the methods and proprties of the child. It's particulary helpful in two cases : the chaining of constructors, and method overriding.

In the chaining of constructors, as we know , when the constructor of the child is invoked, it automatically invokes the constructor of the parent, and if there is no default constructor for the parent, the system can't guess what constructor to be invoked instead and how to pass the arguments to it. So, in the case of no default constructor in the parent, the developer has to invoke the paren't constructor manually, and this is when base comes in hand.

Using base as a function in a constructor function of the child invokes the constructor of the parent class. Here's an example:

var Shape = classing.Class({
	protected : {
		height: null,
		width : null,
	},
	public : {
		Construct : Function.create(xTyped , [
			types(Number,Number),
			function(a , b) {
				this.height = a;
				this.width = b;
			}
		]),
		Height : {
			get : function() {return this.height;},
			set : function(value) {this.height = value;}
		},
		Width : {
			get : function() {return this.width;},
			set : function(value) {this.width = value;}
		},
		Area : function() {
			return "Not Implemented";
		}
	}
});

var Rectangle = classing.Class.Extends(Shape)({
	public : {
		Construct : Function.create(xTyped, [
			types(),
			function() {
				base(0,0);
			},
			types(Number,Number),
			function(x,y) {
				base(x,y);
			}
		]),
		Area : function() {
			return this.width*this.height;
		}
	}
});
				

Here we changed in the Shape class and added a 2-arguments constructor and no default constructors, and in the constructors of the Rectangle class we invoked the Shape constructor using base as a function and passed to it the desired arguments.

In the case of methods overriding, sometimes we just need to add functionality to the overriden method not change it completely. To do this we can invoke the parent implemetation of the method inside the overriding instance in the child using base.methodName() and then add the new functionality we want. Here's an example:

var Person = classing.Class({
	public : {
	    Greet : function() { return "Hi"; }
	}
});
var HotelResptionest = classing.Class.Extends(Person)({
	public : {
		Greet : function() {
			return base.Greet() + ", Welcome to our hotel"; //returns "Hi, Welcome to our hotel"
		}
	}
});
				

Heads Up!

  • base can be used as function only inside the constructor of the child class.
  • Although it's not a reserved word, you should treat base as if it was a reserved word. Naming any of your variables with base may result in an unexpected behaviour.

The 'Final' Keyword

Final is used for two purposes :

For final methods , the method is wrapped with the function classing.Final(or with the Final global shortcut) like we do with wrapping static components with the function Static. Here's an example:

var Person = classing.Class({
	protected : {
		name : null,
		age : null,
	},
	public : {
		Construct : Function.create(xTyped , [
			types(String,Number),
			function(a , b) {
				this.name = a;
				this.age = b;
			}
		]),
		getInfo : Final(function() {return "Name: " + this.name + ", Age: " + this.age;})
	}
});
				

Attempting to override a final method will throw an error.

var VIP = classing.Class.Extends(Person)({
	public : {
		getInfo : function(){return "VIP";} //throws an error
	}
});	
				

To create final classes, classing.Final.Class is used in the following manner:

//for a parent class				
var ClassName = classing.Final.Class({
	/* Your defintion goes here */
});

//for a child class
var ClassName = classing.Final.Class.Extends(someParent)({
	/* Your defintion goes here */
})
				

Here's an example:

var Parent = classing.Class({
	protected : {
		name: null,
		age : null,
	},
	public : {
		Name : {
			get : function() {return this.name;},
			set : function(value) {this.name = value;}
		},
		Age : {
			get : function() {return this.age;},
			set : function(value) {this.age = value}
		}
	}
});

var InfertileChild = classing.Final.Class.Extends(Parent)({});

var ImpossibleChild = classing.Class.Extends(InfertileChild)({}) //throws an error