Comprender las enumeraciones scala

122

Tengo que decir que no entiendo las clases de enumeración de Scala. Puedo copiar y pegar el ejemplo de la documentación, pero no tengo idea de lo que está sucediendo.

object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
  • ¿Qué significa type WeekDay = Valuey por qué tengo que escribir eso?
  • ¿Por qué es val Mon = Value? ¿Y eso que significa?
  • ¿Por qué tengo que importar el WeekDay objeto? Y,
  • cuando escribo val day = WeekDay.Mon, ¿por qué es tipo WeekDay.Value, no tipo WeekDay?
Karel Bílek
fuente
2
He escrito una pequeña descripción general sobre Scala Enumeración y alternativas, puede que le resulte útil: pedrorijo.com/blog/scala-enums/
pedrorijo91
Rasgos sellados proporcionan una excelente alternativa - stackoverflow.com/questions/11203268/what-is-a-sealed-trait
Joey Baruch

Respuestas:

150

el Enumerationrasgo tiene un miembro de tipo que Valuerepresenta los elementos individuales de la enumeración (en realidad es una clase interna, pero la diferencia no importa aquí).

Por lo tanto, object WeekDayhereda ese miembro de tipo. La línea type WeekDay = Valuees solo un alias de tipo . Es útil, porque después de importarlo en otro lugar import WeekDay._, puede usar ese tipo, por ejemplo:

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

En cambio, una versión mínima sería:

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

y no tiene que importar el contenido de object WeekDay, pero luego necesitaría usar type WeekDay.Valuey calificar miembros individuales. Entonces el ejemplo sería

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

La segunda pregunta es sobre el significado de val Mon, ... = Value. De hecho, esto es muy confuso si no analiza la implementación de Enumeration. ¡Esta no es la asignación de un tipo! En su lugar, está llamando a una protegida método del mismo nombre , Valueque devuelve una instancia concreta del tipo Value.

Se da la circunstancia de que puede escribir val a, b, c = fooen Scala, y para cada valor a, by cel método foose llama una y otra vez. Enumerationusa este truco para incrementar un contador interno para que cada valor sea individual.

Si abre los documentos de la API de Scala Enumerationy hace clic en Visibility: All, verá aparecer ese método.

0__
fuente
2
Gracias, esto es muy confuso pero creo que es correcto. Usaré clases de mayúsculas y minúsculas en su lugar, parece 100% más fácil.
Karel Bílek
2
Personalmente, también prefiero las clases de cajas selladas. Un poco más detallado, pero menos hokus-pokus con contadores internos mutables, etc. Con Scala 2.10, hay algunas ideas de cómo las enumeraciones (que a diferencia de Java no son una construcción de lenguaje sino solo una solución de biblioteca) se pueden escribir mejor usando macros.
0__
@ 0__ ¿Puedo preguntar por qué y cómo utiliza la clase sellada para reemplazar la enumeración en Scala? ¿Hay algo malo con la enumeración de Scala?
x1a0
¿Qué pasa si los valores de Enum tienen miembros? ¿Cómo definiría, por ejemplo, el horario de apertura de cada día de la semana como: lunes (8,20), ..., sol (0,0)?
simou
1
@simou, entonces deberías usar un rasgo sellado y subclases reales. Sin embargo, difícilmente llamaría a ese escenario una "enumeración". Será mejor que escribas Open(Mon, 8, 20)y los días seguirán siendo una enumeración plana.
0__