Case objects vs Enumerations in Scala

前端 未结 14 1005
误落风尘
误落风尘 2020-11-22 16:45

Are there any best-practice guidelines on when to use case classes (or case objects) vs extending Enumeration in Scala?

They seem to offer some of the same benefits.

14条回答
  •  囚心锁ツ
    2020-11-22 17:26

    Case objects already return their name for their toString methods, so passing it in separately is unnecessary. Here is a version similar to jho's (convenience methods omitted for brevity):

    trait Enum[A] {
      trait Value { self: A => }
      val values: List[A]
    }
    
    sealed trait Currency extends Currency.Value
    object Currency extends Enum[Currency] {
      case object EUR extends Currency
      case object GBP extends Currency
      val values = List(EUR, GBP)
    }
    

    Objects are lazy; by using vals instead we can drop the list but have to repeat the name:

    trait Enum[A <: {def name: String}] {
      trait Value { self: A =>
        _values :+= this
      }
      private var _values = List.empty[A]
      def values = _values
    }
    
    sealed abstract class Currency(val name: String) extends Currency.Value
    object Currency extends Enum[Currency] {
      val EUR = new Currency("EUR") {}
      val GBP = new Currency("GBP") {}
    }
    

    If you don't mind some cheating, you can pre-load your enumeration values using the reflection API or something like Google Reflections. Non-lazy case objects give you the cleanest syntax:

    trait Enum[A] {
      trait Value { self: A =>
        _values :+= this
      }
      private var _values = List.empty[A]
      def values = _values
    }
    
    sealed trait Currency extends Currency.Value
    object Currency extends Enum[Currency] {
      case object EUR extends Currency
      case object GBP extends Currency
    }
    

    Nice and clean, with all the advantages of case classes and Java enumerations. Personally, I define the enumeration values outside of the object to better match idiomatic Scala code:

    object Currency extends Enum[Currency]
    sealed trait Currency extends Currency.Value
    case object EUR extends Currency
    case object GBP extends Currency
    

提交回复
热议问题