ステートマシン - enumは州の選択ですか?

私は状態としてクラス静的変数を持っていたいが、Objective Cはそれを許可しなかった

状態クラスに対して +(int)LOOPING_STATE を試しましたが、失敗します

switch (myCurrentState) {
case [STATE_CLASS LOOPING_STATE]:   <== received an error of "expression can't be put here"
return;
}

enumは一般に状態コードを書くための選択ですか?

他に選択肢はありますか?それらのオプションをどのような条件で使用すべきですか?

前もって感謝します。

2

2 答え

これはObjective-Cとはほとんど関係がありませんが、Objective-CではCと多く関係しています。一般に、状態マシンの状態を表すためにenumを使用するのは、単純な整数よりも優先されるべきです。

スイッチでクラスを使用できない理由は、switch文のcaseラベルで使用される式の値をコンパイル時に知る必要があるためです。 [STATE_CLASS LOOPING_STATE] がクラスメソッドを呼び出すと、コンパイラはコンパイル時にその式の結果を安全に知ることができないため、switch文の生成を拒否します。

なぜコンパイラはコンパイル時に大文字小文字のラベルに使用される式の結果を知る必要がありますか? switch文の背後にあるアイデアは、一連の意味的に同等のif/else ifブロックよりも効率的です。これは、スイッチステートメントを無条件ジャンプを伴うディスパッチテーブルに変換することによって達成されるが、if/else if解決策は多くの条件付きジャンプを必要とする。簡単に推測できるように、コンディショナルジャンプは、パイプライン全体をフラッシュする可能性があるため、現代のパイプライン型CPU設計とは根本的に矛盾しています。 (現代のCPUは洗練された分岐予測で補償しようとしますが、問題を完全に回避できれば良いでしょう)

しかし、それを正しいものにしておくことはまず最初に来て、それを速くします。

4
追加された
あなたのstatemachineのヘッダーの中のenumを宣言することは、すべての状態数がとにかく有限でなければならないので、うまくいくはずです。これらの定数をグローバルに定義する列挙型の問題はありません(結局のところ、シンボルだけに興味があり値ではありません)。
追加された 著者 Johannes Rudolph,
説明のための多くのTHX。私は列挙型で定義されたグローバル定数が嫌いです、クラスの下で状態を定数にする方法はありますか?それとも、私がしたいことをするための他の選択肢がありますか?ありがとう!
追加された 著者 Unreality,

この状態マシンが高速である必要がある場合は、列挙型を使用します。しかし、これを行うためのオブジェクト指向の方法が必要な場合、各状態の機能は、状態オブジェクト自体のメソッドになります。したがって、switch/ifステートメントをすべて削除することになります。ステートマシンのループは次のようになります:

-(void) run
{
    State* currentState;

    currentState = [self startState];
    while (currentState != [self stopState])
    {
        currentState = [currentState transitionWitInput: inputs 
                                                actions: actions];
    }
}

inputs is the input data for the state transition, actions is a block or a selector or an NSInvocation or something that tells the state what to do during the transition.

3
追加された