1

Let's say I have the following enum defined:

import enumeratum._
import enumeratum.EnumEntry.Lowercase

import scala.collection.immutable

sealed trait Day extends EnumEntry with Lowercase

object Day extends Enum[Day]{
  case object MON extends Day
  case object TUE extends Day
  case object WED extends Day
  /* ... */
  override def values: immutable.IndexedSeq[Day] = findValues
}
println(Day.Mon)           // MON, but I would like to see mon instead
println(Day.Mon.entryName) // mon

I would like to override Day.toString to return the entry name instead of class name. But seems that it is not so intuitive.

What I have tried:

  1. Manually override toString to return entryName:
sealed trait Day extends EnumEntry with Lowercase {
  override def toString: String = entryName
}

But it produces StackOverflowError (related to lazy val):

Exception in thread "main" java.lang.StackOverflowError
    at example.Day$MON$.enumeratum$EnumEntry$$stableEntryName(Day.scala:17)
    at enumeratum.EnumEntry.entryName(EnumEntry.scala:21)
    at enumeratum.EnumEntry.entryName$(EnumEntry.scala:21)
    at example.Day$MON$.enumeratum$EnumEntry$Lowercase$$super$entryName(Day.scala:17)
    at enumeratum.EnumEntry$Lowercase.enumeratum$EnumEntry$Lowercase$$stableEntryName(EnumEntry.scala:122)
    at enumeratum.EnumEntry$Lowercase.enumeratum$EnumEntry$Lowercase$$stableEntryName$(EnumEntry.scala:122)
    at example.Day$MON$.enumeratum$EnumEntry$Lowercase$$stableEntryName$lzycompute(Day.scala:17)
    at example.Day$MON$.enumeratum$EnumEntry$Lowercase$$stableEntryName(Day.scala:17)
    at enumeratum.EnumEntry$Lowercase.entryName(EnumEntry.scala:120)
    at enumeratum.EnumEntry$Lowercase.entryName$(EnumEntry.scala:120)
    at example.Day$MON$.entryName(Day.scala:17)
    at example.Day.toString(Day.scala:13)
    at example.Day.toString$(Day.scala:13)
    at example.Day$MON$.toString(Day.scala:17)
    at enumeratum.EnumEntry.enumeratum$EnumEntry$$stableEntryName(EnumEntry.scala:23)
    at enumeratum.EnumEntry.enumeratum$EnumEntry$$stableEntryName$(EnumEntry.scala:23)
    at example.Day$MON$.enumeratum$EnumEntry$$stableEntryName$lzycompute(Day.scala:17)
    at example.Day$MON$.enumeratum$EnumEntry$$stableEntryName(Day.scala:17)
  1. Specify which exactly super method to use:

sealed trait Day extends EnumEntry with Lowercase {
  override def toString: String = super[Lowercase].entryName
}

But still SOE.

  1. I know it is possible with manually overriding entry name but it requires writing boilerplate code:

abstract class Day(override val entryName: String) extends EnumEntry {
  override def toString: String = entryName
}

object Day extends Enum[Day]{
  case object MON extends Day("mon")
  case object TUE extends Day("tue")
  case object WED extends Day("wed")
  /* ... */
  override def values: immutable.IndexedSeq[Day] = findValues
}
  1. It works well with StringEnum but again, I will need to write boilerplate code for literals.
Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
  • If this is something that matters just use `entryName` or add your own method that calls `toString.toLowercase`, `toString` shouldn't be used for anything that is not a quick debug on the console. – Luis Miguel Mejía Suárez Dec 03 '20 at 16:41
  • @LuisMiguelMejíaSuárez Thanks, I totally understand that. 1) I would like to have this ability when printing entities to console and have corresponding `toString` and `entryName` values. 2) Anyway, it should not throw SOE. – Andrii Abramov Dec 03 '20 at 16:51
  • 2
    It throws because `entryName` is based on `toString`... so you can not base `toString` on `entryName` :p – Luis Miguel Mejía Suárez Dec 03 '20 at 16:52
  • @LuisMiguelMejíaSuárez yeah, you're right. But I would like it to be redesigned internally in enumeratum a bit. E.g. with `getClass.getSimpleName` or whatever :( – Andrii Abramov Dec 03 '20 at 16:59
  • 1
    Ah but then that is not a question for SO but rather an issue in the **Enumeratum** repo ;) – Luis Miguel Mejía Suárez Dec 03 '20 at 17:01
  • 2
    I doubt author would go for it. Some Java-friendly libraries might depend on runtime reflection and then matching `toString` name might be used to retrieve the value. And FP Scala community is encouraged to use Cats `Show` typeclass for things like that. – Mateusz Kubuszok Dec 03 '20 at 17:02
  • @LuisMiguelMejíaSuárez you are right, but I am not complaining here, maybe someone has a suggestion) – Andrii Abramov Dec 03 '20 at 19:39

0 Answers0