Метод наследования не работает для цепочки 3 и более объектов. Почему?
У меня есть 3 объекта.
netBuilder Numbering NumberingMethodDefault Метод наследования взят с местной статьи. http://javascript.ru/tutorial/object/inheritance Ф-я extend и mixin. extend: function (Child, Parent) { var F = function () {}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.superclass = Parent.prototype; this.mixin(Child, Parent); }, /** * @param {type} dst * @param {type} src * @returns {undefined} */ mixin: function (dst, src) { var tobj = {}; for (var x in src) { if ((typeof tobj[x] == "undefined") || (tobj[x] != src[x])) { dst[x] = src[x]; } } if (document.all && !document.isOpera) { var p = src.toString; if (typeof p == "function" && p != dst.toString && p != tobj.toString && p != "\nfunction toString() {\n [native code]\n}\n") { dst.toString = src.toString; } } } Я делаю наследование Numbering extends from netBuilder NumberingMethodDefault extends from Numbering. oopUtility.extend(Numbering, netBuilder); oopUtility.extend(NumberingMethodDefault, Numbering); И вызываю где надо суперклассы конечно же. Numbering.superclass.constructor.apply(this, arguments); NumberingMethodDefault.superclass.constructor.apply(this, arguments); Numbering имеет метод setNumber(). У меня есть доступ в Numbering к netBuilder методам, но в NumberingMethodDefault я не могу выполнить метод из Numbering setNumber(). Uncaught TypeError: Object #<NumberingMethodDefault> has no method 'setNumber' Тогда я вывел console.log() что же в суперклассе NumberingMethodDefault console.log(NumberingMethodDefault.superclass); //and it was netBuilder, not Numbering! о_О Там почему-то netBuilder, а не Numbering. Хотя в статье описывается, что должно работать с цепочкой и в 3 объекта. Как заставить работать наследование для цепочки 3 и более? |
И да, я пробовал
NumberingMethodDefault.superclass.setNumber.call(this, arguments); Но очевидно получал ошибку, т.к. в netBuilder нет такого метода. |
А у экземпляров Numbering-то setNumber вызывается?
Вы, вероятно, сначала описываете Numbering и его прототип, а потом наследуетесь. Так делать неправильно, ибо extend перезаписывает прототип. var oop = { extend: function (Child, Parent) { var F = function () {}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.superclass = Parent.prototype; this.mixin(Child, Parent); }, /** * @param {type} dst * @param {type} src * @returns {undefined} */ mixin: function (dst, src) { var tobj = {}; for (var x in src) { if ((typeof tobj[x] == "undefined") || (tobj[x] != src[x])) { dst[x] = src[x]; } } if (document.all && !document.isOpera) { var p = src.toString; if (typeof p == "function" && p != dst.toString && p != tobj.toString && p != "\nfunction toString() {\n [native code]\n}\n") { dst.toString = src.toString; } } } }; function netBuilder() { } function Numbering() { } *!* oop.extend(Numbering, netBuilder); */!* // важно отнаследоваться здесь, а не после объявления прототипа! Numbering.prototype.setNumber = function() { alert('Numbering#setNumber'); } function NumberingMethodDefault() { } oop.extend(NumberingMethodDefault, Numbering); new NumberingMethodDefault().setNumber(); |
Цитата:
2) Методы описаны не через прототип, все внутри через this. this.setNumber = function(elem, row, number); Последовательность подключения js файлов верная, следовательно и последовательность вызовов extend. Т.е последовательность: netBulder, Numbering, NumberingMethodDefault. extend вызывается в последних 2-х файлах после объявления объекта. Проблема в том, что все методы в this ? Numbering.prototype после extend уже равен netBuilder же. console.dir(Numbering.prototype); //netBuilder Если я буду добавлять в прототип после, то это уже добавление метода в netBuilder получается. Или идея как раз в том, что у всех общий прототип? |
Цитата:
|
Цитата:
На stackoverflow мне подсказывают, что проблема в mixin. Он копирует же все родительские свойства, в том числе перетирает superclass. Надо добавить туда проверку не копировать superclass, это скорее всего решение. :) |
Вот решение проблемы.
if (((typeof tobj[x] == "undefined") || (tobj[x] != src[x])) && (src[x] != src.superclass)) { dst[x] = src[x]; } Суперкласс теперь не перетирается родительским и наследование работает правильно. Надо написать автору статьи. :) |
Часовой пояс GMT +3, время: 15:22. |