Розуміння перерахунку шкали


122

Треба сказати, що я не розумію перерахування класів 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

Запечатані риси - відмінна альтернатива - stackoverflow.com/questions/11203268/what-is-a-sealed- Portrait
Joey Baruch

Відповіді:


150

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 не є мовною конструкцією, а лише бібліотечним рішенням), можна краще писати за допомогою макросів.
0__

@ 0__ Чи можу я запитати, чому і як ви використовуєте герметичний клас для заміни enum у Scala? Чи є щось погано з перерахуванням Скали?
x1a0

Що робити, якщо самі значення Enum мають члени? Як би ви, наприклад, визначили години роботи для кожного дня тижня, наприклад: пн (8,20), ..., нд (0,0)?
simou

1
@simou, тоді ви дійсно повинні використовувати запечатану ознаку та фактичні підкласи. Навряд чи я би назвав цей сценарій "перерахуванням". Ви можете краще написати, Open(Mon, 8, 20)і дні залишаться рівним перерахуванням.
0__
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.