Virus721
Virus721

Reputation: 8315

JavaScript - Special multiple inheritance

Say i have the following object types :

var Positionable = function() { };
Positionable.prototype.x = 0;
Positionable.prototype.y = 0;

var Sizable = function() { };
Sizable.prototype.w = 0;
Sizable.prototype.h = 0;

var Fadable = function() { };
Fadable.prototype.a = 0;

I would like to have a function allowing me to create a sub type that would inherit from several other types. For example, i could create a type Rectangle that would inherit from both Positionnable and Sizable.

I could chain prototypes :

var Rectangle = function() { };
Sizable.prototype = new Positionable;
Rectangle.prototype = new Sizable;

But i don't like this method fo two reasons :

So i first thought about merging prototypes, assuming i have a function void merge( type dst, type src, bool overwrite ), in loop i would simply merge every base class prototype into the child type prototype. This would not create a chain (which is what i want as explained above)

But this causes another problem : since i'm not using new, the base constructors are not called. So i wonder, is there a way to also merge constructors ? For example, if i could access and reference the base constructors, i could store each of these base constructors in an array, and assign the child type constructor with a function calling each of these constructors consecutivly.

How could i do this with constructors ? Or maybe there is another way ?

Thanks for your help !

Upvotes: 1

Views: 92

Answers (2)

MingLi
MingLi

Reputation: 46

if you use Object.Create(),you have to think about browser compatibility. you can write
a function to resolve the issue.eg: 

     function multipleinheritPrototype() {
        if (arguments.length == 0) {
            return;
        }
        var args = arguments;
        var sub = args[0];
        var constructor = sub.prototype.constructor;
        if (!Object.create) {
            Object.prototype.create = function (obj) {

                function f() {
                }

                f.prototype = obj;
                return new f();
            };
        }
        var base;
        for (var i = 1; i < args.length; i++) {
            base = Object.create(args[i].prototype);
            for (var attr in base) {
                sub.prototype[attr] = base[attr];
            }
        }
        sub.prototype.constructor = constructor;

    }      
    you can such so use it.
    multipleinheritPrototype(Rectangle, Sizeable, Positionnable);

Upvotes: 0

Felix Kling
Felix Kling

Reputation: 816442

Since JavaScript doesn't support multiple inheritance you have to resolve to mixins. It's like you said, you have to copy the methods of one of the prototypes over to the child prototype.

The constructor functions should be called inside the child constructor function. Here is an example:

var Rectangle = function() {
    Sizeable.call(this);
    Positionnable.call(this);
};
// Rectangle inherits from Sizeable
Rectangle.prototype = Object.create(Sizeable.prototype);
// Mixin Positionnable
merge(Rectangle.prototype, Positionnable.prototype);

// alternatively you could mixin both of the prototypes

See also: Benefits of using `Object.create` for inheritance


function mixin(Target) {
    var args = arguments;

    // merge prototypes
    for(var i = 1; i < args.length; i++) {
        merge(Target.prototype, args[i].prototype);
    }

    // a new constructor function which calls all 
    // the passed constructor functions
    var F = function() {
        var instance = Target.apply(this, arguments);
        for (var i = 1; i < args.length; i++) {
            args[i].call(instance);
        }
        return instance;
    };
    F.prototype = Target.prototype;
    return F;
};

// usage

Rectangle = mixin(Rectangle, Sizeable, Positionnable);

This works under one assumption: The mixin constructors don't expect any arguments. If you have to pass arguments to them, you have to explicitly call them in the target/child constructor.

Upvotes: 2

Related Questions