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

静的インスタンス(シングルトン)を残して、イベントベースで作業することをお勧めします。ここで、すべての関数を公開しますが、これは望ましくありません。カスタムイベントを使用するのはそれほど難しくありません。これがメインクラスの外観です。

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と呼ばれるオプションのパラメータがあることに注意してください。これには、任意の値(オブジェクト、数値、文字列など)を渡すことができます。できるだけ明確な例として、両方のアクションに1つのイベントクラスを使用しました。さらに詳細なパラメーターを使用して、他のアクションに対してより具体的なカスタムイベントを作成することもできます。たとえば、 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クラスを拡張することができます。

于 2012-09-11T07:46:28.390 に答える
1

うーん。あなたのコードを考えると、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

あなたのコーディングスタイルと報告されたエラーから判断すると、私はあなたがこれをしたと思います。

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 に答える
0

リスナーを登録するとき、Main.instanceはまだ割り当てられていないと思います。ここでメインインスタンスをトレースしようとしましたか?

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 に答える