2013-08-29 2 views
1

Скажет у меня есть следующие типы объектов:JavaScript - Специальное множественное наследование

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; 

Я хотел бы иметь функцию, позволяющую мне создать подтип, который унаследует от нескольких других типов. Например, я мог бы создать тип Rectangle, который наследует как от Positionnable, так и от Sizable.

I Could прототипы цепи:

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

Но я не люблю этот метод Fo по двум причинам:

  • Это вызывает Sizable наследовать от Positionable, что означает, что если я хочу другого тип должен быть значимым без Positionable, я не могу этого сделать;

  • Это означает, что Sizable объект также Positionnable, которые семантически не хорошо, так как нет никаких оснований для Sizable объекта быть Positionnable, а не иначе.

Так я первый подумал о слиянии прототипов, предполагая, что у меня есть функция void merge(type dst, type src, bool overwrite), в цикле я бы просто объединить все базовый класс прототип в типе ребенка прототип. Это не создало бы цепочку (это то, что я хочу, как объяснялось выше)

Но это вызывает еще одну проблему: поскольку я не использую новый, базовые конструкторы не вызываются. Так что интересно, есть ли способ объединить конструкторы? Например, если бы я мог обращаться к базовым конструкторам и ссылаться на них, я мог бы хранить каждый из этих базовых конструкторов в массиве и назначать конструктору дочернего типа функцией, вызывающей каждый из этих конструкторов последовательно.

Как я могу сделать это с помощью конструкторов? Или, может быть, есть другой способ?

Благодарим за помощь!

ответ

2

Поскольку JavaScript не поддерживает множественное наследование, вам необходимо решить mixins. Как вы сказали, вам нужно скопировать методы одного из прототипов на прототип ребенка.

Функции конструктора должны быть вызваны внутри дочернего конструктора. Вот пример:

Смотрите также: 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); 

Это работает при одном предположении: В Смешение конструкторы не ожидают каких-либо аргументов. Если вам нужно передать им аргументы, вы должны явно вызвать их в конструкторе target/child.

+0

Благодарим за помощь. Я, вероятно, сделаю это, если нет другого пути, но «проблема», которую я вижу в этом, заключается в том, что я должен сделать две вещи вместо одной: 1) вызвать родительские конструкторы в дочернем конструкторе, 2) объединить прототипы ,Я хотел бы сделать все это в одной функции, но чтобы иметь возможность сделать это, мне понадобится возможность доступа и назначения конструкторов. Является ли это возможным ? Благодарю. – Virus721

+0

@ Virus721: Вы всегда должны вызывать родительские конструкторы внутри дочернего конструктора, так как здесь происходит вся инициализация, специфичная для экземпляра. Конечно, если родительские конструкторы ничего не делают (т. Е. Они не содержат никакого кода), тогда вам не нужно их вызывать. Вы можете автоматизировать весь процесс, если вам хорошо переопределить функцию «Прямоугольник». Я отправлю пример. –

+0

Функциональность Mixix Dojo пришла на ум, прочитав этот вопрос, и автоматически обрабатывает цепи конструктора. В зависимости от ваших потребностей и требований я бы предложил изучить его. – Phix

0
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); 
+0

'Object.create' легко масштабируется, если вы используете его только с первым аргументом: https://developer.mozilla.org/en-US/ документы/Web/JavaScript/Справка/Global_Objects/Объект/создать # Polyfill. Btw, вам нужно назначить функцию 'Object.create', а не' Object.prototype.create'. –

+0

Спасибо. Выглядит также интересно, я попробую. – Virus721