1
\$\begingroup\$

i had made a small code snippet for multiple inheritance in js. this code is working for me but actually i like to get the review, that its good and if any problem; provide the solution. etc. the code snippet is below.

/**
 * WebbaseUtility provide the bundle of utilities used for support the webbase
 * functionalities;
 * @package : WebbaseUtility;
 * @version : 1.0.0;
 */
var WebbaseUtility = {};

/**
 * ObjectExt module extends the object properties and functionalities like inheritance etc;
 * @module : ObjectExt;
 * @package : Webbase;
 * @version : 1.0.0;
 * @return Object;
 */

var ObjectExt = WebbaseUtility.ObjectExt = (function()  {

    /**
     * ObjectExt Constructor;
     */
    var ObjectExt = function()  {
    };

    /**
     * This method provide inheritance to the object supplied; this method inherit the 
     * public methods from the Parent class to the Child class. this also provide
     * multiple inheritance, in which the method ambiguity is solved by the overriding
     * the last inherited class's method;
     * @access public;
     * @method inherit;
     * @param Object Parent;
     * @param Object Child;
     * @return Object;
     */
    ObjectExt.prototype.inherit = function(Parent, Child)   {
        var TempObj = function(){}, MultipleInheritanceTempObj = function(){};

        MultipleInheritanceTempObj.prototype = Child.prototype;        
        TempObj.prototype = Parent.prototype;

        for(var key in MultipleInheritanceTempObj.prototype)    {
            TempObj.prototype[key] = MultipleInheritanceTempObj.prototype[key]; 
        }
        MultipleInheritanceTempObj = null;
        Child.prototype = new TempObj();

        if(Child.uber === undefined)    {
            Child.uber = Parent.prototype;
        }else   {
            for(var key in Parent.prototype)    {
                Child.uber[key] = Parent.prototype[key];
            }
        }
        Child.prototype.constructor = Child;

        return Child;
    };

    return new ObjectExt();

})();

Child = WebbaseUtility.ObjectExt.inherit(ParentA, Child);
Child = WebbaseUtility.ObjectExt.inherit(ParentB, Child);
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

First of all, I responded to the post in c.l.js, and this content in part reiterates the comments there.

My first thought is that you should look at some of the available mixin libraries. There are many mixin techniques available. And on top of that, there are many interesting approaches layered on top of them. Peter Michaux published one recently on applying mixins to constructor functions. Angus Croll published one on creating functions out of mixins, and together with Dan Webb he also presented this technique at the recent Fluent Conference. I published a rough draft of an article on a still different approach to mixins.

I don't understand the reason for your complex syntactic structure. You assign your ObjectExt variable to the result of an immediately invoked function expression (IIFE). That IIFE involves defining a constructor function, attaching the inherit function to its prototype`, and then constructing and returning an instance of that constructor:

 var ObjectExt = (function () {
     var ObjectExt = function () { };
     ObjectExt.prototype.inherit = function (Parent, Child) {
         // content here
     };
     return new ObjectExt();
 })();

I don't see that any of that serves any purpose over the much simpler version here:

 var ObjectExt = {inherit: function (Parent, Child) {
     // content here
 };

Can you give any reason for the existence of this constructor function, the IIFE, the prototype, etc? It seems to be plain overhead, and serves only to obfuscate your code.

One other minor point is that you probably should declare your key variable once in the top of the inherit function.

But the main issue is that you add properties to the parent.prototype object. In this code:

if(Child.uber === undefined)    {
    Child.uber = Parent.prototype;               // (1)
} else {
    for(var key in Parent.prototype)    {
       Child.uber[key] = Parent.prototype[key];  // (2)
    }
}

in the line marked (1), you create the Child.uber property as reference to the Parent.prototype. So any properties you add when you come through the if-block again and hit (2) will be added to the orignial prototype object. This is a pretty fundamental flaw. An example would be the following:

var Pet = function(name) {this.name = name;}
Pet.prototype.speak = function(){
    console.log(this.name + " speaks.");
};
var WalkingAnimal = function() {};
WalkingAnimal.prototype.walk = function() {
    console.log(this.name + " is walking.");
};
var SwimmingAnimal = function() {};
SwimmingAnimal.prototype.swim = function() {
    console.log(this.name + " is swimming.");
};
var Dog = function(name) {this.name = name;};
WebbaseUtility.ObjectExt.inherit(Pet, Dog);
WebbaseUtility.ObjectExt.inherit(WalkingAnimal, Dog);

var ClownFish = function(name) {this.name = name;};
WebbaseUtility.ObjectExt.inherit(Pet, ClownFish);
WebbaseUtility.ObjectExt.inherit(SwimmingAnimal, ClownFish);

var rover = new Dog("Rover");
var nemo = new ClownFish("Nemo");
rover.walk();  // "Rover is walking";
nemo.swim();   // "Nemo is swimming";
nemo.walk();   // "Nemo is walking";   // WTF?

This is a fairly fundamental design flaw. I think you need to rethink your approach to this problem.

Cheers,

-- Scott

\$\endgroup\$
1
  • \$\begingroup\$ Very good review! \$\endgroup\$
    – oligofren
    Commented Nov 1, 2013 at 11:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.