面试题答案
一键面试Kotlin 实现游戏状态机
- 定义状态:
使用密封类来定义游戏的各种状态。密封类可以确保在
when
表达式中对所有可能的状态进行全面处理。sealed class GameState { object Starting : GameState() object Paused : GameState() object Ended : GameState() data class Completed(val time: Long) : GameState() }
- 状态转换示例:
可以通过一个函数来模拟状态转换,并根据不同的状态进行相应的操作。
可以这样调用这个函数:fun handleGameState(state: GameState) { when (state) { is GameState.Starting -> println("游戏开始") is GameState.Paused -> println("游戏暂停") is GameState.Ended -> println("游戏结束") is GameState.Completed -> println("游戏通关,通关时间:${state.time} 毫秒") } }
fun main() { val completedState = GameState.Completed(120000) handleGameState(completedState) }
数据类和密封类在处理状态转换及数据传递方面的差异和适用场景
- 差异:
- 数据类:
- 主要用于存储数据。它会自动生成
equals()
、hashCode()
、toString()
以及组件解构等方法,方便数据的比较、存储和使用。在游戏状态机中,像Completed
状态需要携带通关时间这种数据时,使用数据类很合适。它专注于数据的封装和传递。 - 数据类可以有继承体系,但在状态处理方面没有像密封类那样的限制和特性,它不强制要求在
when
表达式中覆盖所有情况。
- 主要用于存储数据。它会自动生成
- 密封类:
- 密封类用于定义受限的类继承结构,它的所有子类必须在与密封类本身相同的文件中声明。在状态机中,它能确保
when
表达式中覆盖了所有可能的状态,提供了一种安全的状态处理方式。 - 密封类本身不能有实例,它主要是为了提供一种类型安全的状态分支处理方式,虽然也可以携带数据(如
Completed
数据类作为密封类的子类),但重点在于状态的界定和分支处理,而不是数据的存储特性。
- 密封类用于定义受限的类继承结构,它的所有子类必须在与密封类本身相同的文件中声明。在状态机中,它能确保
- 数据类:
- 适用场景:
- 数据类适用场景:
- 当需要存储和传递特定的数据,并且数据的操作主要围绕其值展开时,如在游戏中记录玩家的得分、通关时间等,使用数据类。
- 密封类适用场景:
- 当需要定义一个有限的状态集合,并且要在代码中对这些状态进行安全的分支处理时,如游戏状态机中的各种状态,使用密封类可以保证代码的健壮性,避免遗漏某些状态处理的情况。
- 数据类适用场景: