Понимание перечислений scala

120

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

object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
  • Что означает type WeekDay = Value и зачем мне это писать?
  • Почему val Mon = Value? Что это значит?
  • Почему мне нужно импортировать WeekDay объект? И,
  • когда пишу val day = WeekDay.Mon, почему это тип WeekDay.Value, а не тип WeekDay?
  • 2
    Я написал небольшой обзор о перечислении scala и его альтернативах, вы можете найти его полезным: pedrorijo.com/blog/scala-enums/
Теги:
enums

1 ответ

148
Лучший ответ

признак Enumeration имеет член типа Value, представляющий отдельные элементы перечисления (это фактически внутренний класс, но разница здесь не имеет значения).

Таким образом, object WeekDay наследует этот член типа. Строка type WeekDay = Value - это просто псевдоним типа. Это полезно, потому что после его импорта в другом месте с помощью import WeekDay._ вы можете использовать этот тип, например:

def isWorkingDay(d: WeekDay) = ! (d == Sat || d == Sun)

Вместо этого минимальная версия была бы следующей:

object WeekDay extends Enumeration {
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}

и вам не нужно импортировать содержимое object WeekDay, но тогда вам нужно будет использовать тип WeekDay.Value и квалифицировать отдельные члены. Таким образом, пример станет

def isWorkingDay(d: WeekDay.Value) = ! (d == WeekDay.Sat || d == WeekDay.Sun)

Второй вопрос касается значения val Mon, ... = Value. Это действительно очень запутанно, если вы не смотрите на реализацию Enumeration. Это не назначение типа! Вместо этого он вызывает защищенный метод с тем же именем, Value, который возвращает конкретный экземпляр типа Value.

Так получилось, что вы можете написать val a, b, c = foo в Scala, а для каждого значения a, b и c метод foo будет вызываться снова и снова. Enumeration использует этот трюк, чтобы увеличить внутренний счетчик, чтобы каждое значение было индивидуальным.

Если вы откроете документы Scala API для Enumeration и нажмите Visibility: All, вы увидите, что этот метод появляется.

  • 2
    Спасибо, это очень запутанно, но я думаю, что это правильно. Вместо этого я буду использовать классы запечатанных случаев, это кажется на 100% проще.
  • 2
    Лично я тоже предпочитаю закрытые занятия. Чуть более многословный, но менее хокус-покус с изменяющимися внутренними счетчиками и так далее. В Scala 2.10 есть некоторые идеи, как перечисления (которые в отличие от Java являются не языковой конструкцией, а просто решением библиотеки) могут быть лучше написаны с использованием макросов.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню