Scala:如何实现自定义枚举

Scala:如何实现自定义枚举,scala,Scala,下面是我的自定义枚举 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) {

下面是我的自定义
枚举

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
的实例,当需要
枚举时,这是一个问题,如下例所示:

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
  }
}
我总是收到以下错误消息:

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))

推断的类型参数[test.DocState.DocState]不符合方法apply的类型参数界限[s最后,我能够为我的状态机获得正确的实现:

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
下面是如何使用状态机的示例:

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

我希望这能有所帮助。

我不太明白您想做什么,但是
枚举
有一些问题使得它不安全,而且看起来您正在以一种非常不寻常的方式使用它。最好像使用
消息
一样,将密封类与case类/对象模式一起使用。我使用枚举来创建有限状态机。