0

我有这种情况,我在我的主类中声明了一个如下所示的函数:

public class Main extends MovieClip
{

    public static var instance:Main;

    public function Main()
    {
        // constructor code
        welcomeScreen();
        instance = this;
    }

    public final function welcomeScreen():void
    {
        //some code in here
    }

    public final function startLevelOne():void 
    {
        //some other code here
    }


}

在其他一些类中,我使用此语句来触发重置:

restart.addEventListener('click', function() {                                      
     Main.instance.welcomeScreen();
});

不知何故,在另一个类中,我尝试对“startLevelOne”使用相同的语句,但它似乎不起作用并给出了休闲错误:

1195: Attempted access of inaccessible method startLevelOne through a reference with static type Main.

有任何想法吗?

更新#1

我尝试访问该函数的类是完整的这个类:

public class LevelBrief extends MovieClip
{

    public function LevelBrief()
    {
        // constructor code
        startBut.addEventListener('click', function() {
            Main.instance.startLevelOne();
        });
    }
}

更新#2

我在这里粘贴了主要定义的完整代码http://pastebin.com/s6hGv7sT

其他类也可以在这里找到http://pastebin.com/s6h3Pwbp

更新#3

即使通过解决方法解决了问题,我仍然无法理解问题出在哪里。

4

5 回答 5

4

我建议保留静态实例(单例),并基于事件工作。现在您将所有功能公开,这是不可取的。使用自定义事件并不难。看看这就是你的Main类的样子:

public class Main extends MovieClip
{
    public function Main()
    {
        this.addEventListener(Event.ADDED_TO_STAGE, handleAddedToStage);
    }

    public function handleAddedToStage(event:Event)
    {
        this.removeEventListener(Event.ADDED_TO_STAGE, handleAddedToStage);

        this.showWelcomeScreen();

        stage.addEventListener(ScreenEvent.SHOW_WELCOME_SCREEN, handleScreenEvent);
        stage.addEventListener(ScreenEvent.SHOW_LEVEL, handleScreenEvent);
    }


    private function handleScreenEvent(event:ScreenEvent):void
    {
        switch (event.type)
        {
            case ScreenEvent.SHOW_WELCOME_SCREEN:
            {
                this.showWelcomeScreen()
                break;
            }
            case ScreenEvent.SHOW_LEVEL:
            {
                // event.data contains level number
                this.startLevel(event.data);
                break;
            }
            default:
            {
                trace("Main.handleScreenEvent :: Cannot find event.type '" + event.type + "'.");
                break;
            }
        }
    }

    private function showWelcomeScreen():void
    {
        trace("show WelcomeScreen")
        //some private code in here
    }

    private function startLevel(level:int):void 
    {
        trace("start level: " + level)
        //some other private code here
    }
}

这就是自定义事件类的外观(ScreenEvent.as)。请注意,它有一个名为data的可选参数。您可以将任何值(对象、数字、字符串等)传递给它。为了使示例尽可能清晰,我对两个动作都使用了一个事件类,您还可以选择为具有更详细参数的其他动作制作更具体的自定义事件,您可以使用ScreenEventLevelEventPlayerEventGameEvent等名称..

在类的顶部定义了(静态常量)类型。一个事件应该只有吸气剂。

package 
{
    import flash.events.Event;

    public class ScreenEvent extends Event
    {
        public static const SHOW_WELCOME_SCREEN:String = "ScreenEvent.showWelcomeScreen";
        // event.data contains level number
        public static const SHOW_LEVEL:String = "ScreenEvent.showLevel";

        private var _data:String;

        public function ScreenEvent(type:String, data:String):void 
        { 
            super(type);
            this._data = data;
        }

        public function get data():String
        {
            return this._data;
        }

        override public function clone():Event 
        { 
            return new ScreenEvent(this.type, this._data);
        }
    }
}

.. 在您的代码中的任何地方,您都可以将事件发送到舞台。

// dispatch event to Main (stage). Should show welcome screen in our case
stage.dispatchEvent(new ScreenEvent(ScreenEvent.SHOW_WELCOME_SCREEN));

// show level 2
stage.dispatchEvent(new ScreenEvent(ScreenEvent.SHOW_LEVEL, 2));

我知道,它的代码有点多,一开始看起来更困难,但如果项目发展壮大,它将有很大帮助。与事件的区别是“这可能发生,当它发生时,做这个”而不是“在这里做这个,在那里做那个”的优点是,如果你在 Main 类中删除事件监听器,什么都不会中断(松散地耦合)。这使得维护更容易,它节省了一个单例,如果你愿意,你可以扩展 Main 类。

于 2012-09-11T07:46:28.390 回答
1

唔。鉴于您的代码,只有一个严重的问题 - PerwollGame 是什么?你在那里public static var instance:PerwollGame;,你给它分配了一个 Main 类型的对象。也许 PerwollGame 有一个startLevelOne()具有不同签名的函数,这会掩盖您在 Main 类中的函数。另外,回答你的其他人也是对的,你永远不应该在你的代码中使用嵌套函数,真的把你的那个监听器从内联声明中去掉。

于 2012-09-11T04:36:10.710 回答
1

我想你写的

Main.startLevelOne();

代替

Main.instance.startLevelOne();
于 2012-09-10T15:31:12.583 回答
0

我假设当您注册监听器时 Main.instance 尚未分配。您是否尝试在此处跟踪 Main 实例?

public function LevelBrief()
{
    // constructor code
    startBut.addEventListener('click', function() {
        Main.instance.startLevelOne();
    });
    trace(Main.instance); // I assume Main.instance is null
}

如果您在 LevelBrief 的另一个方法中添加侦听器会怎么样:

public function registerListeners():void{
        trace("Main.instance == null? -> " + (Main.instance == null)); //not null here if called later.
        startBut.addEventListener('click', function() {
        Main.instance.startLevelOne();
        });
    }
于 2012-09-11T05:17:58.257 回答
0

从您的编码风格和报告的错误来看,我假设您这样做了。

public static function startLevelOne():void

静态方法和实例化对象之间有一条细线。

也永远不要使用嵌套函数

public class LevelBrief extends MovieClip
{

    public function LevelBrief()
    {
        // constructor code
        startBut.addEventListener('click', onMyClick )
    }

    public functiononMyClick (e:Event) {
            Main.instance.startLevelOne();
        });
    }
}
于 2012-09-10T18:25:39.947 回答