2011-10-28 10 views
2

私は状態としてクラスの静的変数を持っていると思いますが、Objective Cのはそれをステートマシン - 状態の選択はenumですか?

を許可されていない、私は国家クラスの+(int)LOOPING_STATEを試してみましたが、それは

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

に失敗しますが、一般的に状態コードを書くための選択肢の列挙です?

他のオプションはありますか?どのような条件でこれらのオプションを使用する必要がありますか?

ありがとうございます。

答えて

3

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

-(void) run 
{ 
    State* currentState; 

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

inputsは、状態遷移のための入力データであり、actionsはブロックまたはセレクタまたは遷移時に何をすべきかの状態を伝えますNSInvocationか何かです。

4

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

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

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

しかし、まずそれを早くして、それを速くします。

+0

説明のための多くのthx。私は列挙型で定義されたグローバル定数が嫌いです、クラスの下で状態を定数にする方法はありますか?それとも、私がしたいことをするための他の選択肢がありますか?ありがとう! – Unreality

+2

ステートマシンのヘッダーの中でenumを宣言することは、すべてのステート数が有限でなければならない場合は問題ありません。これらの定数をグローバルに定義する列挙型の問題はありません(結局のところ、シンボルだけに興味があり値ではありません)。 –

関連する問題