Comprendre les énumérations scala

122

Je dois dire que je ne comprends pas les classes d'énumération Scala. Je peux copier-coller l'exemple de la documentation, mais je n'ai aucune idée de ce qui se passe.

object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
  • Quels moyens type WeekDay = Valueet pourquoi dois-je écrire cela?
  • Pourquoi val Mon = Value? Qu'est ce que ça veut dire?
  • Pourquoi dois-je importer l' WeekDay objet? Et,
  • quand j'écris val day = WeekDay.Mon, pourquoi est-ce du type WeekDay.Value, pas du type WeekDay?
Karel Bílek
la source
2
J'ai écrit un petit aperçu de l'énumération scala et des alternatives, vous pouvez le trouver utile: pedrorijo.com/blog/scala-enums/
pedrorijo91
Les traits scellés offrent une excellente alternative - stackoverflow.com/questions/11203268/what-is-a-sealed-trait
Joey Baruch

Réponses:

150

le Enumerationtrait a un membre de type Valuereprésentant les éléments individuels de l'énumération (c'est en fait une classe interne, mais la différence n'a pas d'importance ici).

Ainsi object WeekDayhérite cet élément de type. La ligne type WeekDay = Valuen'est qu'un alias de type . C'est utile, car après l'avoir importé ailleurs avec import WeekDay._, vous pouvez utiliser ce type, par exemple:

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

Au lieu de cela, une version minimale serait simplement:

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

et vous n'avez pas besoin d' importer le contenu de object WeekDay, mais vous devrez alors utiliser le type WeekDay.Valueet qualifier les membres individuels. Ainsi l'exemple deviendrait

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

La deuxième question concerne la signification de val Mon, ... = Value. C'est en effet très déroutant si vous ne regardez pas l'implémentation de Enumeration. Ce n'est pas l'attribution d'un type! Il appelle plutôt une protégée méthode du même nom , Valuequi renvoie une instance de béton de type Value.

Il se trouve que vous pouvez écrire val a, b, c = fooà Scala, et pour chaque valeur a, bet cla méthode foosera appelée encore et encore. Enumerationutilise cette astuce pour incrémenter un compteur interne afin que chaque valeur soit individuelle.

Si vous ouvrez la documentation de l'API Scala pour Enumerationet cliquez sur Visibility: All, vous verrez cette méthode apparaître.

0__
la source
2
Merci, c'est très déroutant mais je pense que c'est vrai. J'utiliserai plutôt des classes de cas scellés, cela semble 100% plus facile.
Karel Bílek
2
Personnellement, je préfère aussi les classes de cas scellés. Un peu plus verbeux, mais moins hokus-pokus avec des compteurs internes mutables et ainsi de suite. Avec Scala 2.10, il y a quelques idées sur la façon dont les énumérations (qui contrairement à Java ne sont pas une construction de langage mais juste une solution de bibliothèque) peuvent être mieux écrites en utilisant des macros.
0__
@ 0__ Puis-je vous demander pourquoi et comment utilisez-vous une classe scellée pour remplacer enum dans Scala? Y a-t-il quelque chose qui ne va pas avec l'énumération de Scala?
x1a0
Et si les valeurs Enum elles-mêmes avaient des membres? Comment définiriez-vous par exemple les heures d'ouverture pour chaque jour de la semaine comme: Lun (8,20), ..., Dim (0,0)?
simou
1
@simou alors vous devriez en effet utiliser un trait scellé et des sous-classes réelles. J'appellerais à peine ce scénario une "énumération", cependant. Vous feriez mieux d'écrire Open(Mon, 8, 20)et les jours resteraient une énumération plate.
0__