Search code examples
scalatypesenumeration

Scala - Enumeration with value parametrized


I'm wondering if its possible to have Enumerations with one value parametrized.

Something like:

object Animal extends Enumeration {
  val Dog = Value("dog")
  val Cat = Value("cat")
  val Other = Value(?)

  def create(value: String): Animal.Value = {
    Animal.values.find(_.toString == value).getOrElse(Other(value))
  }
}

And, for use, something like:

create("dog") // will return Animal.Dog
create("giraffe") // will return Animal.Other
create("dog").toString // will return "dog"
create("giraffe").toString // will return "giraffe"

That is, to be able to have some values typed, but to leave one free.

Thanks!!! Lucas.


Solution

  • I have to apologize for jumping the gun. I was thinking in Java terms, where an enum is a very rigid thing. Scala, however, is a bit more flexible in that regard. Enumeration does not stop us from extending the enumeration class ourselves.

    Disclaimer: This is probably not a good idea. It works, but I don't know how it will behave with respect to serialization or the other nice properties that ordinary enumerations have. So if it works for you, great! But I can't promise that it's a good solution.

    object Animal extends Enumeration {
      val Dog = Value("dog")
      val Cat = Value("cat")
    
      def create(value: String): Animal.Value = {
        Animal.values.find(_.toString == value).getOrElse(OtherAnimal(value))
      }
    }
    
    // Extending the enumeration class by hand and giving it a `String` argument.
    case class OtherAnimal(name: String) extends Animal.Value {
      override def id = -1
      override def toString = name
    }
    
    println(Animal.create("dog").toString)     // dog
    println(Animal.create("cat").toString)     // cat
    println(Animal.create("giraffe").toString) // giraffe