状态机 - 枚举是状态的选择吗?

发布于 2024-12-12 06:29:18 字数 357 浏览 1 评论 0原文

我想将类静态变量作为状态,但 Objective C 不允许它

我尝试了 +(int)LOOPING_STATE 作为状态类,但它会失败

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

Is enum General the choice forwriting state code?

还有其他选项吗?在什么条件下应该使用这些选项?

提前致谢。

I would like to have class static variables as states, but Objective C disallowed it

I tried +(int)LOOPING_STATE for state class, but it will fail in

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

Is enum generally the choice for writing state codes?

Are there any other options, and under what condition should those options be used?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

话少心凉 2024-12-19 06:29:18

这与 Objective-C 关系不大,而与 Objective-C 中的 C 关系更大。一般来说,使用枚举来表示状态机的状态应该优于普通整数。

不能在 switch 中使用类的原因是 switch 语句的 case 标签中使用的表达式的值需要在编译时已知。假设 [STATE_CLASS LOOPING_STATE] 是类方法的调用,编译器在编译时无法安全地知道该表达式的结果,因此将拒绝生成 switch 语句。

为什么编译器需要在编译时知道用于 case 标签的表达式的结果? switch 语句背后的想法是比一系列语义上等效的 if/else if 块更有效。这是通过将 switch 语句转换为具有无条件跳转的调度表来实现的,而 if/else if 解决方案需要大量条件跳转。人们很容易猜到,条件跳转从根本上与现代流水线 CPU 设计不一致,因为它们可能会导致整个流水线被刷新。 (现代 CPU 试图通过复杂的分支预测来进行补偿,但如果我们能够完全避免这个问题,那就更好了,对吧?)

但是,首先要保证正确,其次才是加快速度。

This has little to do with Objective-C but more with the C in Objective-C. In general, using an enum to represent the states of your state machine should be preferred over plain integers.

The reason you can't use classes in a switch is that the value of the expressions used in the case labels of a switch statement need to be known at compile time. Assuming [STATE_CLASS LOOPING_STATE] is an invocation of a class method, the compiler can't safely know the result of that expression at compile time, and will thus refuse generating a switch statement.

Why does the compiler require knowing the result of expressions used for case labels at compile time? The idea behind a switch statement is to be more efficient than a series of semantically equivalent if/else if blocks. This is achieved by translating a switch statement into a dispatch table with an unconditional jump, whereas the if/else if solution requires lots of conditional jumps. As one can easily guess, conditional jumps are fundamentally at odds with modern pipelined CPU designs since they may cause the entire pipeline to be flushed. (Modern CPUs try to compensate with sophisticated branch prediction, but it would be better if we can avoid the issue altogether, right?)

But then, getting it right comes first, making it fast second.

陌伤浅笑 2024-12-19 06:29:18

如果这个状态机需要快速,那么枚举就是最佳选择。但是,如果您想要一种面向对象的方式来执行此操作,则每个状态的功能将是状态对象本身的方法。因此,您将完全取消 switch/if 语句。您的状态机循环看起来像这样:

-(void) run
{
    State* currentState;

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

inputs 是状态转换的输入数据,actions 是一个块或一个选择器或一个 NSInitation > 或者告诉国家在过渡期间要做什么的东西。

If this state machine needs to be fast, enums are the way to go. However, if you want an object oriented way of doing this, the functionality of each state would be a method of the state object itself. Thus you would do away with the switch/if statement altogether. Your state machine's loop would look something like this:

-(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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文