LoginSignup
6
1

More than 5 years have passed since last update.

Scalaで文字列->Enumにできるようにちょっとだけ使いやすくする

Last updated at Posted at 2018-12-18

scalaでEnum的なことをするときよくこんな感じで実装しますが

sealed abstract class Color
object Color {
  case object Red   extends Color
  case object Blue  extends Color
  case object Green extends Color
}

結構↓みたいな使い方をした場合が多いです。

// 取ってきたデータ(StringやShortとか)からEnumに変換したい
scala> val red = Color("red")
red: Option[Color] = Some(Red)

// valueを持たせたい
scala> Color.Red.code
res17: String = #FF0000

こういう時一個traitを用意してEnumそれを継承するだけで便利になる気がします。

trait Enum[A <: { def name: String }] {
  val values: List[A]
  def apply(name: String): Option[A] = values.find(_.name == name)
}

sealed abstract class Color(val name: String, val code: String)

object Color extends Enum[Color] {
  case object Red   extends Color("red", "#FF0000")
  case object Blue  extends Color("blue", "#0000FF")
  case object Green extends Color("green", "#008000")

  lazy val values = List(Red, Blue, Green)
}

文字列以外も対応したい場合は EnumValue を用意して、必要に応じて extends した方が一番使いやすい気がします。
(こちらに参考しました!)

trait EnumValue {
  type Value
  val value: Value
}

trait Enum[A <: EnumValue] {
  val values: List[A]
  def apply(value: A#Value): Option[A] = values.find(_.value == value)
}

ただし values をいちいち定義して case object 全部入れないといけないのが手間かかりますので…
そこはreflection使うとよりいい簡潔にかけると思いますが、また別の機会に試してみます。

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1