调用函数问题as3

时间:2015-08-24 09:17:06

标签: function actionscript-3 variables parameter-passing call

我正在从子类调用一个函数并将当前的部分变量传递给它然后加载/删除下一部分,一切正常,直到我尝试将相同的变量传递给我之前使用的核心函数。我无法理解为什么它不再起作用了。

以下问题:

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是先前设置的字符串。

我之前使用过这个,它运行正常但不是静态函数。

如果有人可以解释为什么这不起作用我会非常感激,因为我无法让它发挥作用。

2 个答案:

答案 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中的空间将清除所有属性和功能。因此,firstsecond都在RAM中拥有自己的小空间。它们都拥有一个名为a()的函数,因为非静态函数/属性与它们的实例相关联。但是函数b()怎么样?好吧,这个存在于任何实例中独立存在,并且只在你的Ram中存在一次

所以,当你尝试做这样的事情时

first.b();

我猜你假设调用a()实例的函数first。但这是不可能的,因为静态函数不知道你指的是a(),它可能是firstsecond,因为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);
}