Перечисление в Scala и группа значений

Мне нужно сгруппировать некоторые значения Enumeration.

Вот код:

object PostType extends Enumeration {
  // Documents
  val BOOKMARK = Value("bookmark")
  val FILE = Value("file")
  val NOTE = Value("note")
  val WIKIDOC = Value("wikidoc")

  …    
}

object PostTypes {
  type PostTypes = List[PostType.Value]
  val DOCUMENTS : PostTypes = List(PostType.BOOKMARK, PostType.FILE, PostType.NOTE, PostType.WIKIDOC)
  val QUESTIONS : PostTypes = List(PostType.QUESTION, PostType.QUICKPOLL, PostType.SURVEY)
  val EVENT : PostTypes = List(PostType.EVENT)
  …
  val ALL : PostTypes = PostType.values.toList
}

Есть ли способ лучше ? Вот минусы, которые я вижу: PostType.Value и PostTypes.PostTypes в клиентском коде!

[обновить] улучшить код с помощью обоих ответов

object PostType extends Enumeration {
  // Documents
  val Bookmark = Value("bookmark")
  val File = Value("file")
  val Note = Value("note")
  val Wikidoc = Value("wikidoc")
  …
}

object PostTypes {
  import PostType._
  implicit def toList(pt: Value) = List(pt)

  type PostTypes = List[Value]
  val Documents = List(Bookmark, File, Note, Wikidoc)
  val Questions = List(Question, Quickpoll, Survey)
  val All = values.toList
}

[обновление 2] Еще несколько улучшений

object PostType extends Enumeration {
  type PostType = Value
  type PostTypes = List[Value]

  implicit def toList(pt: Value) = List(pt)

  // Documents
  val Bookmark = Value(1, "bookmark")
  val File = Value(2, "file")
  val Note = Value(3, "note")
  val Wikidoc = Value(12, "wikidoc")

  // Declare after Val to avoid runtime error
  val Documents = List(Bookmark, File, Note, Wikidoc)
  val Questions = List(Question, Quickpoll, Survey)
  val All = values.toList.sorted
}

person Yann Moisan    schedule 08.02.2014    source источник


Ответы (3)


Ниже приведен подход, который не использует перечисления, но, надеюсь, достигает ваших целей. В примере показано, как создать экземпляр PostType из экземпляра String. Если String не совпадает, выдается MatchError.

package rando

object PostType {
  val all = Document.all ++ Question.all
  def fromString(s: String): PostType = Document.fromString.orElse(Question.fromString)(s)
}
sealed trait PostType

object Document {
  val all = Set(Bookmark, File, Note, Wikidoc)
  val fromString: PartialFunction[String, Document] = {
    case "bookmark" => Bookmark
    case "file" => File
    case "note" => Note
    case "wikidoc" => Wikidoc
  }
}
sealed trait Document extends PostType
case object Bookmark extends Document
case object File extends Document
case object Note extends Document
case object Wikidoc extends Document

object Question {
  val all = Set(SlowPoll, QuickPoll, Survey)
  val fromString: PartialFunction[String, Question]  = {
    case "slowpoll" => SlowPoll
    case "quickpoll" => QuickPoll
    case "survey" => Survey
  }
}
sealed trait Question extends PostType
case object SlowPoll extends Question
case object QuickPoll extends Question
case object Survey extends Question

object Example extends App {
  println(PostType.fromString("bookmark").getClass)
}
person Dave Swartz    schedule 08.02.2014
comment
Мне нужно создать экземпляр PostType из String (данные поступают из текстового файла) - person Yann Moisan; 08.02.2014
comment
Я обновил ответ, чтобы создать экземпляр PostType из String. - person Dave Swartz; 08.02.2014

Я думаю, что это настолько хорошо, насколько это возможно, если вы не хотите использовать альтернативную реализацию Enumeration (см. Мой ответ здесь) или просто используйте константы.

Единственное, что я мог бы предложить, - это определить псевдоним типа type PostType = Value и использовать его вместо Value. Я уверен, что вы знаете, что, импортировав <package>.PostType._, вам больше не нужно будет ставить перед значениями перечисления PostType.

Наконец, PostTypes кажется немного излишним, и его легко спутать с PostType при чтении. Но это всего лишь мелочи. Я использую тот же подход, что и вы, и ничего лучше не знаю.

person yǝsʞǝla    schedule 08.02.2014
comment
скорее, импортировав PostType._, чтобы опустить префикс (импорт PostType.Value, похоже, не работает)? - person Yann Moisan; 08.02.2014

Вот окончательный код с помощью других ответов. Просто нужно import PostType._ в клиентском коде.

object PostType extends Enumeration {
  type PostType = Value
  type PostTypes = List[Value]

  implicit def toList(pt: Value) = List(pt)

  // Documents
  val Bookmark = Value(1, "bookmark")
  val File = Value(2, "file")
  val Note = Value(3, "note")
  val Wikidoc = Value(12, "wikidoc")

  // Declare after Val to avoid runtime error
  val Documents = List(Bookmark, File, Note, Wikidoc)
  val Questions = List(Question, Quickpoll, Survey)
  val All = values.toList.sorted
}
person Yann Moisan    schedule 11.02.2014