使用原型时的 Javascript 继承问题 - 实例被覆盖:(
我是 JavaScript 编程新手,我对继承有一些噩梦。我正在为 Appcelerator Titanium 编写一些代码,并且我希望继承一个名为 Slide2D 的基类。
所以我在Slide2D的原型中放置了一些函数。这些通常不会被覆盖,但将从 Slide2D 派生的类中调用。这些函数也将从程序的其他部分调用。 Titanium 中还有各种用于管理动画的事件处理程序。
如果我在某些调用代码(使用 new)中制作几张这样的幻灯片,
var s = new Slide2D('slide1', 'background1.png', etc......
var t = new Slide2D('slide2', 'background2.png', etc......
那么无论我使用 s 还是 t,我的所有原型方法都会指向最后创建的 Slide2D。因此,即使我使用 s 变量,“slide2”也将始终显示。
这让我发疯 - 任何帮助将不胜感激。
抱歉代码太长,但这里是:
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;
};
};
编辑
非常感谢您的及时回复。我已按照您的建议进行了更改,并解决了该特定问题。
然而,出现了一个新问题。
我需要从派生类 - ExtendedSlide2D 调用 Slide2D.prototype.getView。
但是,现在我收到以下错误:
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();
I'm new to JavaScript programming and I am having a bit of a nightmare with inheritance. I am writing some code for Appcelerator Titanium and I have a base class called Slide2D that I wish to inherit from.
So I have placed a few functions in Slide2D's prototype. These are generally not going to be overwritten, but will be called from classes derived from Slide2D. These functions will also be called from other parts of the program. There are also various eventhandlers used to manage animation in Titanium.
If I make a couple of these slides in some calling code (using new)
var s = new Slide2D('slide1', 'background1.png', etc......
var t = new Slide2D('slide2', 'background2.png', etc......
all of my prototype methods point to the last Slide2D created, regardless of whether I use s or t. So 'slide2' will always be displayed, even if I'm using the s variable.
This is driving me mad - any help would be greatly appreciated.
Sorry for the length of the code but here it is:
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;
};
};
Edit
Thanks very much for your prompt reply. I have made the changes that you recommended and that has resolved that particular problem.
However, a new issue has been introduced.
I need to call Slide2D.prototype.getView from a derived class - ExtendedSlide2D.
However, now I get the following error :
Result of expression 'Slide2D.prototype.getView()' [undefined] is not an object
at ExtendedSlide2D.js at line .......
This is where I add the button to the base class's view object.
I'm sure this error just comes down to my inexperience with the language but, once again, any help would be greatly appreciated.
Once again - here is the code for 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();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要将添加到原型的方法移至 Slide2D 构造函数之外。这样它们只定义一次,而不是在每个对象实例化时都定义一次。
然后让这些原型函数访问“内部”,例如 _name、_slideView 等...您需要将所有“变量”(当前在闭包下可访问)转换为对象本身的属性。然后用“this”引用所有这些成员属性。前缀。
下面,我强行将所有“vars”替换为 this.properties。只有需要从原型方法访问的属性和函数才需要此转换。对于内部函数(例如动画函数),它们仍然可以使用在闭包下可访问的变量。
You'll need to move the methods that you adding to the prototype outside of the Slide2D constructor function. That way they only get defined once instead of with every object instantiation.
And then for those prototype functions to access the "internals", such as _name, _slideView, etc... You will need to convert all your "vars" (currently accessible under closure) to be properties of the object itself. Then reference all those member properties with a "this." prefix.
Below, I brute-forced replaced all your "vars" to be this.properties. Only the properties and function you need to access from the prototype methods need this conversion. For internal functions (such as your animate functions), they may still be able to use vars accessible under closure.