State Machine - Является ли enum выбором для штатов? - PullRequest
2 голосов
/ 28 октября 2011

Я хотел бы иметь статические переменные класса в качестве состояний, но Цель C запретила это

Я пытался +(int)LOOPING_STATE для класса состояния, но это не удастся в

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

Является ли enum обычно выбором для написания кодов штатов?

Есть ли другие варианты, и при каких условиях эти опции должны использоваться?

Заранее спасибо.

Ответы [ 2 ]

4 голосов
/ 28 октября 2011

Это имеет мало общего с Objective-C, но больше связано с C в Objective-C.В целом, использование enum для представления состояний вашего конечного автомата должно быть предпочтительнее простых чисел.

Причина, по которой вы не можете использовать классы в переключателе, заключается в том, что значение выражений, используемых в метках caseоператора switch необходимо знать во время компиляции.Предполагая, что [STATE_CLASS LOOPING_STATE] является вызовом метода класса, компилятор не может безопасно знать результат этого выражения во время компиляции и, таким образом, откажется генерировать оператор switch.

Почему компилятору требуется знатьрезультат выражений, используемых для меток case во время компиляции?Идея оператора switch заключается в том, чтобы быть более эффективным, чем серия семантически эквивалентных блоков if / else if.Это достигается путем перевода оператора switch в таблицу диспетчеризации с безусловным переходом, тогда как решение if / else if требует большого количества условных переходов.Как можно легко догадаться, условные переходы принципиально расходятся с современными конвейерными процессорами, поскольку они могут привести к сбросу всего конвейера.(Современные процессоры пытаются компенсировать с помощью сложного предсказания ветвлений, но было бы лучше, если бы мы вообще могли избежать этой проблемы, верно?)

Но тогда сначала нужно сделать это правильно, а потом быстро.

3 голосов
/ 28 октября 2011

Если этот конечный автомат должен быть быстрым, перечисления - это путь.Однако, если вам нужен объектно-ориентированный способ сделать это, функциональность каждого состояния будет методом самого объекта состояния.Таким образом, вы полностью покончили бы с оператором switch / if.Цикл вашего конечного автомата будет выглядеть примерно так:

-(void) run
{
    State* currentState;

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

inputs - это входные данные для перехода между состояниями, actions - это блок, селектор или NSInvocation, или что-то, что говоритукажите, что делать во время перехода.

...