我有以下代码(简体):
sealed trait Status {
def code: String
}
object Status {
final case object Failed extends Status {
val code: String = "failed"
}
final case object Succeeded extends Status {
val code: String = "succeeded"
}
val allStatuses = List(Failed, Succeded)
}
是否有一种聪明的方法来确保allStatuses
列表中包含Status
的所有可能类型,或者是一种可迭代的,详尽的集合的替代方法?
原因是我希望能够通过在每个对象的String
上进行匹配将Option[Status]
转换为code
,或者如果不匹配则返回None
他们。而且我希望代码安全,以防将来添加更多可能的状态。
答案 0 :(得分:0)
您可以通过scala反射获得它们。首先,您需要导入scala-reflect
库:
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value
然后,您必须借助knownDirectSubclasses
遍历扩展密封类的所有模块:
import reflect.runtime.universe
import reflect.runtime.currentMirror
import reflect.runtime.universe._
def knownSubmodules[T : TypeTag]: List[T] = {
def run(symbol: universe.Symbol): List[T] = {
if (symbol.isModuleClass) {
val moduleMirror = currentMirror.reflectModule(symbol.asClass.module.asModule)
List(moduleMirror.instance.asInstanceOf[T])
}
else if (symbol.isClass && symbol.asClass.isSealed) {
symbol.asClass.knownDirectSubclasses.toList.flatMap(run)
}
else Nil
}
run(symbolOf[T])
}
因此,对于以下继承结构:
sealed trait Base1
case object Foo1 extends Base1
case object Bar1 extends Base1
sealed trait Base2 extends Base1
case object Foo2 extends Base2
case object Bar2 extends Base2
它将返回所有4个对象:
scala> knownSubmodules[Base1]
res1: List[Base1] = List(Bar1, Bar2, Foo2, Foo1)
答案 1 :(得分:0)
我建议这样的事情:
object Status extends Enumeration {
case class FieldVal(code: String) extends Val(nextId)
type Status = FieldVal
val FAILED = FieldVal("Failed")
val SUCCEEDED = FieldVal("Succeeded")
def fromString(value: String): Status = {
values.find(v => v.asInstanceOf[Status].code.equals(value))
.map(_.asInstanceOf[Status])
.getOrElse(FAILED)
}
}