以下是我的自定义Enumeration
...
object DocState extends Enumeration { thisenum =>
type DocState = State
val New = Value("new", new FromNew)
val Open = Value("open", new FromOpen)
class State(name: String, convertWith: Transduction) extends Val(name) {
def apply(message: Save) = convertWith(message)
def apply(message: Edit) = convertWith(message)
}
protected final def Value(
name: String, convertWith: Transduction
) = new State(name, convertWith)
sealed trait Message
case class Save(text: String) extends Message
case class Edit(text: String) extends Message
def apply(name: String) = thisenum.withName(name).asInstanceOf[State]
}
trait Transduction {
def apply(message: Save)
def apply(message: Edit)
}
class FromNew extends Transduction {
def apply(message: Save): DocState = { ... }
def apply(message: Edit): DocState = { ... }
}
class FromOpen extends Transduction {
def apply(message: Save): DocState = { ... }
def apply(message: Edit): DocState = { ... }
}
......它的工作原理如下:
import DocState._
val currentState = New(Save("hello")) // currentState is New
val newState = currentState(Edit("hello")) // newState is Open
上面的代码工作得很好......但是New
和Open
是State
的实例,而不是DocState
的实例,而Enumeration
时这是一个问题需要1}},如下例所示:
trait DocException[S <: Enumeration] extends ServiceException {
val state: Option[S]
}
object DocException {
def apply[S <: Enumeration](message: String, _state: Option[S]) = new RuntimeException(message) with DocException[S] {
val state: Option[S] = _state
}
}
以下代码无法编译:
val e = DocException("state error", Some(New))
我总是收到以下错误消息:
inferred type arguments [test.DocState.DocState] do not conform to method apply's type parameter bounds [S <: Enumeration]
[error] val e = DocException("state error", Some(New))
/home/j3d/Projects/test/app/DocFsm.scala:71: type mismatch;
[error] found : Some[test.DocState.DocState]
[error] required: Option[S]
[error] val e = DocException("state error", Some(New))
我错过了什么吗?有没有更好的方法来实现我的自定义Enumeration
?
答案 0 :(得分:0)
最后,我能够为我的状态机获得正确的实现:
object DocState extends Enumeration { thisenum =>
type DocState = Value
val New = Value("new", new FromNew)
val Open = Value("open", new FromOpen)
class Val(name: String, convertWith: Transduction) extends super.Val(name) {
def !(message: Save) = convertWith(message)
def !(message: Edit) = convertWith(message)
}
private def Value(name: String, convertWith: Transduction) = new Val(name, convertWith)
sealed trait Message
case class Save(text: String) extends Message
case class Edit(text: String) extends Message
def apply(name: String) = thisenum.withName(name).asInstanceOf[Val]
implicit def toVal(value: Value) = value.asInstanceOf[Val]
implicit def toString(state: DocState) = state.toString
}
trait Transduction {
def apply(message: Save)
def apply(message: Edit)
}
class FromNew extends Transduction {
def apply(message: Save): DocState = { ... }
def apply(message: Edit): DocState = { ... }
}
class FromOpen extends Transduction {
def apply(message: Save): DocState = { ... }
def apply(message: Edit): DocState = { ... }
}
以下是如何使用状态机的示例:
import DocState._
// initialize the state machine
val state1 = DocState("new") // state1 is New
// send an edit message to state1
val state2 = state1 ! Edit("my comment") // state2 is Edit
我希望有所帮助。