Thursday, March 31, 2011

javascript object oriented programming 3 - inheritance

inheritance - more details

Let's review the simple inheritance example in my last  blog:

//constructor method
function Person(name, sex) {
       this.name = name;
       this.sex = sex;
   }
//define Person prototype 
Person.prototype = {
       getName: function() {
           return this.name;
       },
       getSex: function() {
           return this.sex;
       }
}
//define an Employee constructor method
function Employee(name, sex, employeeID) {
    this.name = name;
    this.sex = sex;
    this.employeeID = employeeID;
}

Employee.prototype = new Person();
Employee.prototype.getEmployeeID = function() {
    return this.employeeID;
};
As we said, there are some problems in this inheritance. Let's address these problems one by one.
1. When we create the Employee constructor method and protoype, we also have to create a Person instance. It is not reasonable and not efficient.
To fix this issue, we should try to inherit the prototype only. We should put reusable properties and methods into prototype. Let's change our code:
Employee.prototype = Person.prototype;

In this way, every time we create a new Employee object, it can access any methods and properties in Person's prototype too. And we don't need to instance a Person object.

2. Another problem is Employee's prototype is completely re defined, this will cause Employee's constructor is referencing to the wrong object. Try the code below:


var e = new Employee('henry', 'm', 25);
console.log(e.constructor == Employee); //false
The constructor is not pointing to itself. To fix this issue, we simply change our code to this:
Employee.prototype = Person.prototype;
Employee.prototype.constructor = Employee.
3. Directly copying Person's prototype to Employee's prototype is easy and efficient. But it does bring some side effects. Employee's prototype is pointing to the same object, the Person's prototype, Employee's prototype properties and methods will complete override its parent object's prototype's same name properties and methods.
For example, if we also define a getName method in Employee's prototype:
Employee.prototype.getName = function(){return 'henry'};
var p = new Person('Jack', 'm');
p.getName(); //henry

To fix this issue, we must break the chain. We need to introduce an intermediary. We create an empty functoin F(){} first. Then we set its prototype to Person's prototype: F.prototype = Person.prototype. Now, let's see how we should do the inheritance:
function F(){};
F.prototype = Person.prototype;
Employee.prototype = new F();
Employee.prototype.constructor = Employee;

4. How to call parent object's method in child object? Javascript doesn't have someting like PHP's 'parent::' feature. There are several implementations for this. I just use a simple and traditional way: uber property. Finally the inheritance mechanism is:
var F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype;

What is the uber? Let's change our Person's getName method:
getName: function() {
var parentName = '';
if (this.constructor.uber) {
if (this.constructor.uber.getName) {
         parentName = this.getName();
}
   }
   return this.name + "'s parent is " + parentName;
}

No comments: