Как я могу извлечь общую логику перечисления Scala в черту или суперкласс? - PullRequest
0 голосов
/ 01 июня 2018

Мне нужно определить группу схожих перечислений:

object Color extends MyEnum[Color.Color] {
  type Color = Value
  val Red, Green, Periwinkle = Value
}

object Shape extends MyEnum[Shape.Shape] {
  type Shape = Value
  val Square, Circle, Balbis = Value
}

Я бы хотел извлечь разделяемую функциональность в абстрактный класс или черту для поддержки 1) apply и unapply методов,и 2) неявные преобразования из перечислений в их строковые представления:

abstract class MyEnum[T] extends Enumeration {
  implicit def valueToString(value: T): String = value.toString
  implicit def stringToValue(string: String): T = apply(string)

  def unapply(arg: String): Option[T] =
    values.find(_.toString == arg).map(_.asInstanceOf[T])

  def apply(arg: String): T =
    values.find(_.toString == arg)
      .getOrElse(sys.error(s"Invalid value '$arg'"))
      .asInstanceOf[T]
}

Это не компилируется;когда я добавляю параметр типа в MyEnum[Color.Color], он по какой-то причине нарушает тип Value.

Есть ли какой-то способ получить то, что я хочу, с помощью этого синтаксиса enum, или мне нужно переключиться нарешение кейс-объекта (или что-то более сложное)?

1 Ответ

0 голосов
/ 01 июня 2018

В этом блоге обсуждается ад перечисления в Scala: scala-enumerations-hell

Решение состоит не в том, чтобы использовать тип перечисления Scala, а в создании собственного класса перечисления,Вот абстрактный класс из этого блога:

abstract class Enum[Enum : ClassTag] { self =>
  val values = {
    import runtime.universe._
    val mirror = runtimeMirror(self.getClass.getClassLoader)
    val classSymbol = mirror.classSymbol(self.getClass)

    classSymbol.toType.members
      .filter(_.isModule)
      .map(symbol => mirror.reflectModule(symbol.asModule).instance)
      .collect { case v: Enum => v }
  }

  def forName(name: String): Option[Enum] = values.find(_.name == name)

  implicit class RichardEnum(enum: Enum) {
    def name: String = enum.toString
  }
}

Существует также структура, которая обеспечивает это для вас: lloydmeta / enumeratum

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...