Tuesday, 3 March 2015

Enums for scala

Scala has very limited implementation of Enumeration. Enumerated objects can't extends other classes. Partial replacement for it is to use sealed classes. You can do pattern matching on them. When you ommit some possible value you will get compiler warning for not exhaustive pattern matching. One missing feature is that you can't get sorted values of all objects extending them. You can simple got it using my (40-lines) EnumOf class from scala-enum. Examples below.

Declaration

sealed abstract class Color(red: Double, green: Double, blue: Double)

object Color extends EnumOf[Color] {
  case object Red   extends Color(1, 0, 0)
  case object Green extends Color(0, 1, 0)
  case object Blue  extends Color(0, 0, 1)
  case object White extends Color(0, 0, 0)
  case object Black extends Color(1, 1, 1)
}

Usage

Color.values shouldEqual List(Red, Green, Blue, White, Black)

Color.valueOfOpt("Blue").value shouldEqual Blue
Color.valueOfOpt("NotExisiting").isEmpty shouldBe true

You can also enumerate on objects nested in instances

Declaration

case class DistanceFrom(srcCity: String, srcCoordinates: Coordinate) extends EnumOf[DistanceBetween] {

  case object ToBerlin extends DistanceFromSrcCityTo("Berlin", Coordinate(52.5075419, 13.4251364))
  case object ToNewYork extends DistanceFromSrcCityTo("New York", Coordinate(40.7033127, -73.979681))

  abstract class DistanceFromSrcCityTo(val destCity: String, val destCoordinates: Coordinate) extends DistanceBetween {
    override def srcCoordinates: Coordinate = DistanceFrom.this.srcCoordinates
  } 
}

sealed abstract class DistanceBetween {
  def srcCoordinates: Coordinate
  
  def destCity: String
  def destCoordinates: Coordinate

  def inKm: Int = Coordinate.distanceInKm(srcCoordinates, destCoordinates).toInt
}

Usage

val DistanceFromWarsaw = DistanceFrom("Warsaw", Coordinate(52.232938, 21.0611941))

DistanceFromWarsaw.ToBerlin.inKm shouldEqual 519
DistanceFromWarsaw.ToNewYork.inKm shouldEqual 6856

DistanceFromWarsaw.values.map(_.inKm) shouldEqual List(519, 6856)

No comments:

Post a Comment