我正在从子类调用一个函数并将当前的部分变量传递给它然后加载/删除下一部分,一切正常,直到我尝试将相同的变量传递给我之前使用的核心函数。我无法理解为什么它不再起作用了。
以下问题:
1180:调用可能未定义的方法setupSection。
最初我设置参数并从标准函数加载类:
public function setupVariables():void {
//Main code here
//Establish Section
currentSection = secData;
setupSection(currentSection);
}
public function setupSection(sectionHolder:String):void {
//Here selects the right choice from an Array and loads new Section.
}
//I call the function from the child
Main.changeSection("loadNext");
public static function changeSection(lSection:String):void {
var lSection : String;
currentSection = lSection;
trace("Val Passed = " +currentSection);
//TraceOutput is - Val Passed = loadNext
setupSection(currentSection);
}
public function setupSection(sectionHolder:String):void {
//LoadSection etc. . .
}
违规命令似乎是这样的:
setupSection(currentSection);
currentSection是先前设置的字符串。
我之前使用过这个,它运行正常但不是静态函数。
如果有人可以解释为什么这不起作用我会非常感激,因为我无法让它发挥作用。
答案 0 :(得分:0)
静态函数无法调用实例函数。静态本质上是全局的,不与类的任何实例相关联,因此它不能调用实例函数,因为它不是一个实例,并且不知道存在什么(如果有的话)实例。
如果你真的希望将changeSection()
保留为静态函数,那么你可以做的是将类的实例作为参数传递,以便你可以在实例上调用setupSection()
。例如:
public static function changeSection(lSection:String, main:Main):void {
var lSection : String; currentSection = lSection;
trace("Val Passed = " +currentSection);
//TraceOutput is - Val Passed = loadNext
main.setupSection(currentSection);
}
如果您在调用该函数时无法轻松访问该类的实例,那么您尝试执行的操作更像是singleton。在这种情况下,您需要为单个实例存储静态引用,以便您可以从任何地方轻松访问它。然后,您只需要实例函数,并通过对实例的静态引用来调用它们。例如:
class Main {
public static var main:Main;
public var currentSection:String;
public function Main() {
main = this;
}
public function changeSection(section:String):void {
currentSection = section;
setupSection(currentSection);
}
public function setupSection(section:String):void {
// setup section
}
}
现在,您可以在目前正在进行的任何地方使用Main
课程,例如:
Main.main.changeSection("loadNext");
我应该提一下,这通常不被认为是一个好的设计,因为您将代码全局耦合到Main
。正如您在某种意义上已经发现的那样,这会变得更加混乱和难以扩展。更好的解决方案是使用事件或dependency injection。
使用事件需要更多设置,但从长远来看,它通常更清洁,问题更少。我从不后悔将深度耦合的代码重构为事件。
首先,您可以定义一个漂亮的小型自定义事件类,它告诉您一个部分应该更改(您不必总是需要一个自定义事件类,您可以使用通用Event
类,但是一个自定义class允许您为事件定义自定义数据:
public class SectionEvent extends Event {
public static var SECTION_CHANGE:String = "sectionChange";
public var section:String;
public function SectionEvent(type:String, section:String){
super(type, true); // bubbles=true, important later
this.section = section;
}
}
现在,您可以收听此活动并在Main
课程中处理(我假设它是一个文档课程):
class Main extends MovieClip {
public function Main(){
addEventListener(SectionEvent.SECTION_CHANGE, sectionChangeHandler);
}
private function sectionChangeHandler(event:SectionEvent):void {
changeSection(event.section);
}
public function changeSection(section:String):void {
currentSection = section;
setupSection(section);
}
private function setupSection(section:String):void {
// setup section
}
}
现在要更改该部分,只需调度该事件(来自Main
的任何子显示对象,它会冒出来,因为我们设置了bubbles = true),如下所示:
dispatchEvent(new SectionEvent(SectionEvent.SECTION_CHANGE, "nextSection"));
希望您可以看到,尽管这会增加一些额外的代码,但它可以更好地组织它。它使Main
看起来非常平易近人,非常清楚地描述了事件的动作,并且不易理解和使用。流程的每个部分都是紧密encapsulated段代码,您可以比以前更轻松地理解,扩展和测试。
答案 1 :(得分:0)
正如@Aaron在他的回答中指出的那样(以及我的初始评论),静态函数/属性与类的实例无关。
为了更彻底地解释这一点,我将举一个例子。假设我们有一个名为Main
的类和一个名为Section
的类。
class Section extends Sprite{
public Section(){}
public function a():void{
//this is a function of an instance
}
public static function b():void{
//a static function of the class
a();//this will not work
}
}
class Main extends Sprite{
public Main(){
var first:Section = new Section();
var second:Section = new Section();
}
}
如您所见,我们的Main类创建了Section类的两个实例。对于您拥有的每个实例,RAM中的空间将清除所有属性和功能。因此,first
和second
都在RAM中拥有自己的小空间。它们都拥有一个名为a()
的函数,因为非静态函数/属性与它们的实例相关联。但是函数b()
怎么样?好吧,这个存在于任何实例中独立存在,并且只在你的Ram中存在一次。
所以,当你尝试做这样的事情时
first.b();
我猜你假设调用a()
实例的函数first
。但这是不可能的,因为静态函数不知道你指的是a()
,它可能是first
或second
,因为b()
存在外面他们。
希望我的解释很容易理解:)
但是让我们实际解决你的问题,没有任何静态功能。正如我的一条评论中所提到的,你可以(应该?)在这里使用事件。我会放弃Custom Event Shenanigans,而是提供一个更简单(但更多hacky)的解决方案。
在setupSection()
函数中,您可能会执行类似这样的操作
public function setupSection(sectionHolder:String):void{
var s:Section = //you get the appropiate child instance somehow
addChild(s);
}
您需要做的是监听到从此实例调度的事件,如下所示:
var s:Section = //yadayada
s.addEventListener(Event.CHANGE, onSectionChange);
addChild(s);
在您的Child类中,当您想要更改Section时,不要调用静态函数,而是执行此操作
var e:Event = new Event(Event.CHANGE);
e['sectionname'] = //the desired section
dispatchEvent(e);
现在,在调度Event之后,将调用Main实例中的函数onSectionChange
。适当的功能看起来像这样
private function onSectionChange(e:Event):void{
var sectionname:String = e['sectionname'];
setupSection(sectionname);
}