Наследование: конструктор не работает "супер"? - PullRequest
4 голосов
/ 02 января 2012

Я столкнулся с таким поведением после использования JS в течение нескольких месяцев.Я очень озадачен из-за своего фона Java: я создаю класс и делаю подклассы.Вызов конструктора подкласса не вызовет родительский конструктор.Хорошо, я читал об этом поведении, оно кажется нормальным, верно?

Посмотрите этот пример jsfiddle , чтобы помочь мне прояснить.

Итак, чтобы мой конструктор подкласса запускал каждый изего родительский конструктор, я добавляю следующее (см. jsfiddle пример

Хорошо, кажется, работает лучше таким образом. Теперь я задаюсь вопросом о следующем; есть ли способуказать, какой суперкласс без триггера и его конструктор? Как, например, следующий метод Node () запускается следующим образом:

GameObject.prototype = new Node();
GameObject.prototype.constructor=GameObject;

(см. обновленный jsfiddle пример )

Iне могу не почувствовать, что я делаю это неправильно. Поскольку моя настоящая модель разделена на 7 подклассов, мои конструкторы имеют 21 вызов (6 + 5 + 4 + 3 + 2 + 1 = 21).

Я что-то не так делаю? Спасибо за ваше время!

Ответы [ 4 ]

2 голосов
/ 02 января 2012

Вы не делаете ничего плохого, по сути.Это ожидаемое поведение с учетом вашего кода.Однако вы можете использовать подход, аналогичный описанному в «Простое наследование JavaScript» Джона Резига .Другое обсуждение подобного подхода можно найти здесь в stackoverflow .

1 голос
/ 25 марта 2013

Вам не нужно вызывать конструктор родителя только для настройки цепочки наследования. См. http://js -bits.blogspot.com / 2010/08 / javascript-inheritance-done-right.html

Следующее плохо, запускает родительский конструктор только для настройки цепочки прототипов

GameObject.prototype = new Node();
GameObject.prototype.constructor = GameObject;

Лучший способ - использовать суррогатный конструктор, который присоединяет прототип без создания экземпляра «суперкласса».

// Surrogate constructor
var TempCtor = function(){};
TempCtor.prototype = Node.prototype;
// Setup the prototype chain without side effects
GameObject.prototype = new tempCtor();
GameObject.prototype.constructor=GameObject;

И вам нужно убедиться, что вы вызываете родительский конструктор из подкласса

function GameObject() {
    // Call the parent's constructor
    Node.call(this);
}

Я обновил ваш jsfiddle с примером, показывающим правильный способ настройки наследования http://jsfiddle.net/2caTD/5/

1 голос
/ 02 января 2012

Как правило, вы делаете это правильно. Но ваша функция конструктора создает свойства для своих экземпляров, и эти свойства присваиваются прототипу наследующего конструктора.

Subclass.prototype.animations, например, находятся на прототипе, совместно используемом всеми последующими экземплярами Subclass. Из вашего кода кажется, что вы намеревались создать эти animations заново для каждого экземпляра.

Как решить эту проблему? Не используйте функции конструктора вообще. Используйте объектные литералы и Object.create.

var Node = {
    init: function () { this.animations = []; },
    doSomething: function () { console.log(this.animations); }
};

var GameObject = Object.create(Node);
GameObject.doSomethingElse = function () { this.init(); this.doSomething(); }

Создайте экземпляр таким же образом вы наследуете:

var gameObj = Object.create(GameObject);
gameObj.doSomethingElse();

Это не должно быть сложнее, чем это.

См. Объединение наследования с шаблоном модуля .

1 голос
/ 02 января 2012

Насколько я понимаю, JavaScript не наивно реализует классы, как это делают традиционные языки, такие как C ++, Java и C #. Я думаю, что вы можете получить желаемое поведение, используя среду JavaScript, которая навязывает поведение, к которому вы привыкли в таких языках, как Java.

Moo Tools - одна из таких структур: http://mootools.net

...