#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")
}
Мои вопросы
- Какой предпочтительный способ определения перечисления
- В чем разница между первым и вторым
- И если я хочу сопоставить регистр в строке, которая возвращает любое из вышеуказанных значений. Какой из них я должен использовать
- В чем разница между наличием типа 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:
Первое не является перечислением. Вы могли бы исключить расширенное перечисление и достичь того же результата. Это всего лишь синглтон с несколькими строковыми константами