Вопрос по enums, scala – Понимание перечислений scala

119

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

object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
What means type WeekDay = Value and why do I have to write that? Why is val Mon = Value? What does that even mean? Why do I have to import the WeekDay object? And, when I write val day = WeekDay.Mon, why is it type WeekDay.Value, not type WeekDay?
Я написал небольшой обзор перечисления scala и его альтернатив, вы можете найти его полезным: pedrorijo.com/blog/scala-enums/ pedrorijo91

Ваш Ответ

1   ответ
149

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

таким образомobject WeekDay наследует этот тип члена. Линияtype WeekDay = Value это простоtype alias, Это полезно, потому что после импорта его в другом месте сimport WeekDay._Вы можете использовать этот тип, например:

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

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

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

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

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

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

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

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

Лично я тоже предпочитаю закрытые занятия. Чуть более многословный, но менее хокус-покус с изменяющимися внутренними счетчиками и так далее. В Scala 2.10 есть некоторые идеи, как перечисления (которые в отличие от Java являются не языковой конструкцией, а просто решением библиотеки) могут быть лучше написаны с использованием макросов.
@ 0__ Могу я спросить, почему и как вы используете закрытый класс для замены enum в Scala? Что-то не так с Перечислением Scala?
@simou, тогда вы действительно должны использовать запечатанную черту и фактические подклассы. Однако вряд ли я бы назвал этот сценарий «перечислением». Вы могли бы лучше написатьOpen(Mon, 8, 20) и дни останутся неизменным перечислением.
Что, если у самих ценностей Enum есть члены? Например, как бы вы определили часы работы для каждого дня недели, например: пн (8,20), ..., вс (0,0)?
Спасибо, это очень запутанно, но я думаю, что это правильно. Вместо этого я буду использовать классы запечатанных случаев, это кажется на 100% проще. Karel Bílek

Похожие вопросы