Проблема наследования JavaScript при использовании прототипов - экземпляры перезаписываются :( - PullRequest
6 голосов
/ 28 февраля 2011

Я новичок в программировании на JavaScript, и мне приснился кошмар с наследованием. Я пишу код для Appcelerator Titanium, и у меня есть базовый класс Slide2D, от которого я хочу наследовать.

Итак, я поместил несколько функций в прототип Slide2D. Как правило, они не будут перезаписаны, но будут вызываться из классов, производных от Slide2D. Эти функции также будут вызываться из других частей программы. Существуют также различные обработчики событий, используемые для управления анимацией в Titanium.

Если я сделаю пару слайдов в коде вызова (используя новый)

var s = new Slide2D('slide1', 'background1.png', etc......
var t = new Slide2D('slide2', 'background2.png', etc......

все мои методы-прототипы указывают на последний созданный Slide2D, независимо от того, использую я s или t. Поэтому «slide2» всегда будет отображаться, даже если я использую переменную s.

Это сводит меня с ума - любая помощь будет принята с благодарностью.

Извините за длину кода, но вот он:

function Slide2D(name, backgroundImage, transform, inAnimation, outAnimation)
{
Titanium.API.info('Slide2D - Constructor - ' + name);

var _self = this;

var _name = name;

var _backgroundImage = backgroundImage;

var _startingTransform = transform;

var _slideView = Titanium.UI.createView({
    backgroundImage: _backgroundImage,
    transform: transform
});

    var _animateInAnimation = Titanium.UI.createAnimation();
_animateInAnimation.transform = Titanium.UI.create2DMatrix().translate(0,0);
_animateInAnimation.duration = 750;

var _animateOutAnimation = Titanium.UI.createAnimation();
_animateOutAnimation.transform = Titanium.UI.create2DMatrix().translate(-1024,0);
_animateOutAnimation.duration = 750;

var onAnimateInStart = function()
{
    Titanium.API.info('Slide2D.onAnimateInStart');
    Titanium.App.fireEvent('animateInStart', {slideName: _name});

    _animateInAnimation.removeEventListener('start', onAnimateInStart);
};

var onAnimateOutStart = function()
{
    Titanium.API.info('Slide2D.onAnimateOutStart');
    Titanium.App.fireEvent('animateOutStart', {slideName: _name});

    _animateInAnimation.removeEventListener('start', onAnimateOutStart);
};

var onAnimateInComplete = function()
{
    Titanium.API.info('Slide2D.onAnimateInComplete');
    Titanium.App.fireEvent('animateInComplete', {slideName: _name});

    _animateInAnimation.removeEventListener('complete', onAnimateInComplete);
};

var onAnimateOutComplete = function()
{
    Titanium.API.info('Slide2D.onAnimateOutComplete');
    Titanium.App.fireEvent('animateOutComplete', {slideName: _name});

    _animateOutAnimation.removeEventListener('complete', onAnimateOutComplete);
};

_animateInAnimation.addEventListener('start', onAnimateInStart);
_animateOutAnimation.addEventListener('start', onAnimateOutStart);

_animateInAnimation.addEventListener('complete',onAnimateInComplete);
_animateOutAnimation.addEventListener('complete', onAnimateOutComplete);

Slide2D.prototype.animateIn = function(){
    Titanium.API.info('Slide2D.prototype.animateIn - ' + _name);

    _slideView.animate(_animateInAnimation);
};

Slide2D.prototype.animateOut = function(){
    Titanium.API.info('Slide2D.prototype.animateOut');

    _slideView.animate(_animateOutAnimation);
};

    Slide2D.prototype.getName = function()
{
    return _name;
};

Slide2D.prototype.getView = function(){
    Titanium.API.info('Slide2D.prototype.getView');
    return _slideView;
};

Slide2D.prototype.getStartingTransform = function(){
    return _startingTransform;
};
 };

Редактировать

Большое спасибо за ваш быстрый ответ. Я внес изменения, которые вы рекомендовали и которые решили эту конкретную проблему.

Однако появилась новая проблема.

Мне нужно вызвать Slide2D.prototype.getView из производного класса - ExtendedSlide2D.

Однако теперь я получаю следующую ошибку:

Result of expression 'Slide2D.prototype.getView()' [undefined] is not an object
   at ExtendedSlide2D.js at line .......

Здесь я добавляю кнопку в объект представления базового класса.

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

Еще раз - вот код для ExtendedSlide2D:

Titanium.include('Slide2D.js');



function ExtendedSlide2D(name, backgroundImage, transform, inAnimation, outAnimation)
{

Titanium.API.info('ExtendedSlide2D - Constructor');


this.base = new Slide2D(name, 
                            backgroundImage, 
                            transform, 
                            inAnimation,     
                            outAnimation);



ExtendedSlide2D.prototype.constructor = ExtendedSlide2D;



var button = Titanium.UI.createButton({title: 'AnimateOut',
                                           height: 40,
                                           width: 200,
                                           top: 50

});

button.addEventListener('click', function()

{
    Slide2D.prototype.animateOut();

});


Slide2D.prototype.getView().add(button);
}



ExtendedSlide2D.prototype = new Slide2D();

1 Ответ

2 голосов
/ 28 февраля 2011

Вам нужно переместить методы, которые вы добавляете в прототип, за пределы функции конструктора Slide2D. Таким образом, они определяются только один раз, а не при каждом создании объекта.

И затем для того, чтобы эти функции-прототипы получили доступ к «внутренним элементам», таким как _name, _slideView и т. Д. ... Вам нужно будет преобразовать все ваши «vars» (в настоящее время доступные при закрытии) в свойства самого объекта. Затем укажите все эти свойства элемента с помощью «this». Приставка.

Ниже я грубо-принудительно заменил все ваши "переменные" на это. Свойства. Только преобразования и свойства, к которым вам нужно получить доступ из методов-прототипов, нуждаются в этом преобразовании. Для внутренних функций (таких как ваши анимационные функции) они все еще могут использовать переменные, доступные при закрытии.

function Slide2D(name, backgroundImage, transform, inAnimation, outAnimation) {

    Titanium.API.info('Slide2D - Constructor - ' + name);

    _self = this;

    this._name = name;

    this._backgroundImage = backgroundImage;

    this._startingTransform = transform;

    this._slideView = Titanium.UI.createView({
        backgroundImage: this._backgroundImage,
        transform: transform
    });

    this._animateInAnimation = Titanium.UI.createAnimation();
    this._animateInAnimation.transform = Titanium.UI.create2DMatrix().translate(0, 0);
    this._animateInAnimation.duration = 750;

    /// ...

};

Slide2D.prototype.animateIn = function () {
    Titanium.API.info('Slide2D.prototype.animateIn - ' + this._name);

    this._slideView.animate(this._animateInAnimation);
};

Slide2D.prototype.animateOut = function () {
    Titanium.API.info('Slide2D.prototype.animateOut');

    this._slideView.animate(this._animateOutAnimation);
};

Slide2D.prototype.getName = function () {
    this._name;
};

Slide2D.prototype.getView = function () {
    Titanium.API.info('Slide2D.prototype.getView');
    this._slideView;
};

Slide2D.prototype.getStartingTransform = function () {
    this._startingTransform;
};
...