我曾尝试在 Scala 中实现 StateMachine,但是我遇到了类型系统的问题,这让我很困惑。在下面的代码中,我需要让守卫函数接受一个预期的 StateMachine 子类的参数。不幸的是,由于FunctionN参数的类型参数是逆变的,我不知道如何解决这个问题。
类转换[S,+M <:StateMachine[S]](开始:S,结束:S,var guard:Option[M => Boolean]){ // 上面的编译器错误:^^ 协变类型 M 出现在方法保护的 type => Option[M => Boolean] 的逆变位置 ^^ val startState = 开始 val endState = 结束 def willFollow(stateMachine: M, withGuard: Boolean) = // 上面的编译器错误:^^ 协变类型 M 出现在值 stateMachine 的类型 M 的逆变位置 ^^ if (!withGuard && guard == None) true; 否则(withGuard && guard.get(stateMachine)) } 类 EpsilonTransition[S, M <: StateMachine[S]](start: S,end :S) extends Transition[S, M](start, end, None) 类StateMachine[S](转换:Set[Transition[S,StateMachine[S]]],initialStates:Set[S]){ 私人 val stateDrains = transitions.groupBy(_.startState); 私有 var activeStates = initialStates 默认行为() = { var entryStates = Set[S]() var exitStates = Set[S]() stateDrains.foreach {排水 => val (exitState, transitionsOut) = drain // 跟随非 epsilon 转换 transitionsOut.filter(_.willFollow(this, true)).foreach {transition => exitStates += transition.startState entryStates += transition.endState } } // 对于所有退出状态,我们将状态映射到一组转换,并且所有集合都“扁平化”为一个大的转换集 // 然后它将被那些没有保护的过滤器(epsilon 转换)。生成的过滤转换列表 // 所有都包含我们将映射到的 endStates。所有这些结束状态都附加到当前的入口状态集。 entryStates = entryStates ++ (exitStates.flatMap(stateDrains(_)).filter(_.willFollow(this, false)).map(_.endState)) // 只排除我们没有重新进入的退出状态 // 然后包括新进入的状态 activeStates = ((activeStates -- (exitStates -- entryStates)) ++ entryStates) } 覆盖 def toString = activeStates.toString } 对象 HvacState 扩展枚举 { 类型 HvacState = 值 val 空调、加热器、风扇 = 值 } 导入 HvacState._ 对象 HvacTransitions { val autoFan = new EpsilonTransition[HvacState, HVac](空调, 风扇) val turnOffAc = new Transition[HvacState, HVac](空调, 风扇, Some(_.temperature 75)) val HeaterToFan = new Transition[HvacState,Hvac](加热器、风扇、一些(_.temperature > 50)) } 导入 HvacTransitions._ HVac 类扩展 StateMachine[HvacState](Set(autoFan, turnOffAc, AcToHeater, HeaterToAc, HeaterToFan), Set(heater)) { 变量温度 = 40 }