2012-06-16 3 views
120

Должен сказать, что я не понимаю классы перечисления Scala. Я могу скопировать пример из документации, но я понятия не имею, что происходит.Понимание 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/ – pedrorijo91

ответ

149

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 использует этот трюк, чтобы увеличить внутренний счетчик, чтобы каждое значение было индивидуальным.

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

+2

Спасибо, это очень запутанно, но я думаю, что это правильно. Вместо этого я буду использовать закрытые классы, на 100% проще. –

+2

Я лично предпочитаю закрытые классы дел. Немного более многословный, но менее хокус-pokus с изменяемыми внутренними счетчиками и так далее. С Scala 2.10 есть некоторые идеи, как перечисления (которые в отличие от Java не являются языковой конструкцией, а просто библиотечным решением) могут быть написаны лучше с использованием макросов. –

+0

@ 0__ Могу ли я спросить, почему и как вы используете закрытый класс для замены enum в Scala? Что-то не так с перечислением Scala? – x1a0

Смежные вопросы