Scala:如何实现自定义枚举

3天

这是我的习惯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

上述工作正常的代码......但NewOpen是实例State,而不是实例DocState,这是当一个问题Enumeration需要像在这里下面的例子:

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

3天

最终,我能够为我的状态机获得正确的实现:

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

希望对您有所帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章