通用密封特征fromString()方法

时间:2017-06-27 10:09:24

标签: scala

考虑以下代码:

sealed trait Foo {
  def name: String
}

case object FooA extends Foo {
  override val name: String = "a"
}

case object FooB extends Foo {
  override val name: String = "b"
}

object Foo {
  def fromString(name: String): Foo = {
    name match {
     case FooA.name => FooA
     case FooB.name => FooB  
  }
}

我可以重构fromString()方法以避免每个案例对象实例有一个案例吗?一些更通用的代码能够枚举所有Foo实例?

在我的真实版本中,我开始有很多案例对象,case bla.name => bla的墙壁让我很无聊^^

谢谢:)

2 个答案:

答案 0 :(得分:1)

这样的事情怎么样?

sealed trait Foo {
  def name: String
}

object Foo {
  case object FooA extends Foo {
    override val name: String = "a"
  }

  case object FooB extends Foo {
    override val name: String = "b"
  }

  val values = Seq(FooA, FooB)

  def withName(name: String): Option[Foo] = {
    values.find(value => value.name.equals(name))
  }
}

然后,您可以使用withName(String)方法将相应类型为Foo的具体对象作为Option

val testFooAName = "a"
val testFooA = Foo.withName(testFooAName) // Will yield Some(FooA)

testFooA match {
    case Some(Foo.FooA) => println("Matched Foo.FooA!")
    case Some(Foo.FooB) => println("Matched Foo.FooB!")
}

val testFooNoneName = "none"
val testFooNone = Foo.withName(testFooNoneName) // Will yield None

Output:
Matched Foo.FooA!

答案 1 :(得分:1)

Beachape提供了一个枚举库,可以立即为您完成此操作:

将此包含在您的build.sbt

"com.beachape" %% "enumeratum" % "1.5.15"

提供的Enum类只需要像这样扩展:

import enumeratum._

sealed trait Foo

object Foo extends Enum[Foo] {
  case object FooA extends Foo 
  case object FooB extends Foo 
}

有一个名为withName的函数,通过它的字符串名称,您可以获取正确的密封特征:

Foo.withName("FooA")