Considering the following code :
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
}
}
Can I refactor the fromString() method to avoid having a case per case object instance ? Some more generic code able to enumerate through all Foo instances ?
In my real version, I start to have a lot of case object, and the wall of case bla.name => bla
is boring me ^^
Thanks :)
How about something like this?
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))
}
}
You can then use the withName(String)
method to get the corresponding concrete object of type Foo
as an 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!
Beachape provide an enum library which can do this for you out of the box:
include this in your build.sbt
"com.beachape" %% "enumeratum" % "1.5.15"
The Enum
class provided just needs to be extended like so:
import enumeratum._
sealed trait Foo
object Foo extends Enum[Foo] {
case object FooA extends Foo
case object FooB extends Foo
}
There is a function called withName
that will allow you to get the right sealed trait via its string name:
Foo.withName("FooA")
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.