Разница в определении перечисления в Scala

#scala #enums

#scala #перечисления

Вопрос:

В scala в чем разница в определении перечисления, как показано ниже

 object TargetRelation extends Enumeration {
 
  val Organizations = "organizations"
  val Individuals   = "individuals"
  val Things        = "things"

}

object TargetRelation extends Enumeration {

  type TargetRelation = Value

  val Organizations = Value("organizations")
  val Individuals   = Value("individuals")
  val Things        = Value("things")

}
  

Мои вопросы

  1. Какой предпочтительный способ определения перечисления
  2. В чем разница между первым и вторым
  3. И если я хочу сопоставить регистр в строке, которая возвращает любое из вышеуказанных значений. Какой из них я должен использовать
  4. В чем разница между наличием типа TargetRelation = Value и отсутствием его в перечислении

Вот фрагмент кода

Примечание: target.ResourceType — это строка

 target.resourceType match {
  case TargetRelationType.Individuals => {}
  case TargetRelationType.Organizationse => {}
}
  

Ответ №1:

Этот:

 object TargetRelation extends Enumeration {

  type TargetRelation = Value

  val Organizations = Value("organizations")
  val Individuals   = Value("individuals")
  val Things        = Value("things")

}
  

будут использоваться встроенные объекты и типы Enumeration признаков для:

  • генерировать имена для каждого Value
  • назначьте порядок каждому Value
  • предоставить методы для синтаксического анализа String в Value

где TargetRelation.Value — фактический тип перечисления (именно поэтому люди иногда присваивают ему псевдоним имени сопутствующего объекта и напрямую импортируют псевдоним).

Этот:

 object TargetRelation extends Enumeration {
 
  val Organizations = "organizations"
  val Individuals   = "individuals"
  val Things        = "things"

}
  

нигде не используется Value , поэтому он практически такой же, как этот:

 object TargetRelation {
 
  val Organizations = "organizations"
  val Individuals   = "individuals"
  val Things        = "things"
}
  

значение — это просто пространство имен для констант String s.

Однако, с точки зрения безопасности типов, оба вряд ли полезны, поскольку ни один из них не может быть проверен на исчерпываемость.

 targetRelation match {
  case TargetRelation.Organizations => ...
  // no warning or error about which cases are missing
}
  

Если вам нужно что-то, что работает как Enum : синтаксический анализ имен, автоматизация генерации имен и упорядочения, проверка полноты — оба подхода устарели сообществом, которое вместо этого приняло sealed trait s с case object помощью s (и enumeratum):

 // this ensured that matching is exhaustive
sealed trait TargetRelation
object TargetRelation  {

  case object Organizations extends TargetRelation
  case object Individuals extends TargetRelation
  case object Things extends TargetRelation
}
  
 // like above but with tons of utilities
import enumeratum._

sealed trait TargetRelation extends EnumEntry
object TargetRelation extends Enum[TargetRelation] {

  case object Organizations extends TargetRelation
  case object Individuals extends TargetRelation
  case object Things extends TargetRelation

  val values = findValues
}
  

С помощью этого вы можете использовать TargetRelation.withName("organizations") на этапе синтаксического анализа (есть поддержка Circe и многих других библиотек) и сравнивать проанализированное значение с объектами case закрытой иерархии, которая является типобезопасной, быстрее и т.д.

Ответ №2:

Первое не является перечислением. Вы могли бы исключить расширенное перечисление и достичь того же результата. Это всего лишь синглтон с несколькими строковыми константами