我非常沮丧。我正在按照教程并自己模仿它。到目前为止,我已经能够解决大部分错误,但是这个错误让我难过。我已经尝试用教程标本替换所有类文件,但我仍然得到错误。
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.senocular.utils::KeyObject/construct()
at com.senocular.utils::KeyObject()
at com.asgamer.basics1::Ship()
at com.asgamer.basics1::Engine()
现在,并没有真正理解错误我粘贴在线转储文件供您查看。
Ship class: textbin.com/78z35
Engine class: textbin.com/32b24
KeyObject class: textbin.com/p2725
由于在使用标本类文件时仍然出现错误,我真的不知道从哪里开始。我很乐意尝试任何建议。
答案 0 :(得分:5)
提示:如果允许调试,异常将告诉您源代码中引发错误的确切行。假设您正在使用Flash IDE,请转到发布设置,然后在Flash选项卡中选中“允许调试”。这会让事情变得更容易。
无论如何,您有错误消息。如果仔细阅读,可以缩小问题的范围。我不知道你是一个程序员还是你有兴趣成为一个程序员;如果你不是,这个答案将有希望解决这个特殊的问题。无论如何,如果你不介意漫无边际,让我告诉你,如果你有兴趣成为一名更好的程序员,关注错误并学习如何调试/解决问题是你需要开发的最重要的能力之一(如果不是最重要的那个);所以也许这会给你一些提示,你可以用来解决其他问题。
消息说:
无法访问的属性或方法 空对象引用。
这意味着,在某些时候,你做了类似这样的事情:
someobject.someMethod();
或
someobject.someProperty = "foo";
有些对象碰巧是空的。 您无法调用方法或访问null 的属性。
好的,现在你知道,在某个地方,变量的值为null。请注意,定义属性变量的事实并不意味着它实际上包含一个对象。
这只是说一个名为mySprite的变量可以保存一个Sprite类型的对象:
var mySprite:Sprite;
但是在某些时候你创建一个Sprite并将其分配给mySprite,mySprite保存的值将为null。如果你这样做:
mySprite.x = 0;
在初始化mySprite之前(即在为其指定Sprite之前),您将获得相同的Null Reference错误。
此错误消息还提供了一些帮助上下文,您可以利用这些上下文(在他们过去 ... Flash中的错误是沉默的;当事情不起作用时,您必须手动追查问题)。
好的,让我们打破这个错误信息:
at com.senocular.utils::KeyObject/construct()
at com.senocular.utils::KeyObject()
at com.asgamer.basics1::Ship()
at com.asgamer.basics1::Engine()
上面的内容称为堆栈跟踪。它基本上会告诉你代码爆炸的位置,并且还给出了一些背景信息:你是如何实现的。
第一行告诉错误实际发生的位置。也就是KeyObject对象中的构造方法。该方法是从KeyObject构造函数调用的,而后者又是从Ship构造函数调用的,而构造函数又是从Engine构造函数调用的。
现在,让我们分析一下堆栈跟踪后自下而上的方法:
引擎构造函数中的代码:
ourShip = new Ship(stage);
这会创建一个新的Ship对象。它将对舞台的引用传递给Ship构造函数方法。
Ship构造函数中的代码:
this.stageRef = stageRef;
key = new KeyObject(stageRef);
它抓住了上一步中传递的引用。它存储它并创建一个新的KeyObject对象。 KeyObject构造函数传递给阶段的引用(与从引擎传递到Ship的引用相同)。
KeyObject构造函数中的代码:
KeyObject.stage = stage;
keysDown = new Object();
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
现在我们已经到了错误消息告诉你问题的地步。因此,在某个地方,您使用的是一个保存null并尝试访问其某个方法或属性的变量。
此KeyObject存储对在静态变量中传递的阶段的引用,并创建一个新的Object对象。到目前为止,没有问题。 KeyObject不能为null(它是对Class的引用)。第二行本身也不能有这个空问题。因此,如果这是该方法中的所有代码,则问题必须在第三行或第四行。两者都访问您传递的阶段引用并尝试在其上调用方法(addEventListener)。所以,如果一个失败,另一个也会失败。然后,第三行:这就是问题所在。
因此,此时stage
为空。如前所述,您无法在null上调用方法,这就是错误告诉您的内容。
现在,如果你回到第一个方法调用,你会发现这是问题的根源:
ourShip = new Ship(stage);
你可以非常肯定,在这一点上,舞台是空的。将其添加到Engine扩展MovieClip(这又是一个DisplayObject)的事实,以及任何DisplayObject只有在添加到显示列表时才引用舞台对象这一事实。结论:当运行构造函数时,Engine的实例未附加到显示列表。
修复此问题的方法(可能还有其他方法)可能是将Engine构造函数中的代码移动到单独的函数中,该函数仅在/当Engine对象具有对stage对象的有效引用时才会执行。
public function Engine() : void {
if(stage) {
initialize();
} else {
addEventListener(Event.ADDED_TO_STAGE,initialize);
}
}
private function initialize(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE,initialize);
// here goes the code that's currently in Engine constructor
}
希望这有帮助。
答案 1 :(得分:1)
我觉得你的舞台属性是空的。
你必须自己测试一下舞台对象的痕迹。
在Engine类的构造函数的第一行中,添加:
trace(stage);
在此行上方添加:
ourShip = new Ship(stage);
如果它跟踪“null”那么那就是你的问题。