Scala-Aufzählungen verstehen

122

Ich muss sagen, dass ich Scala-Aufzählungsklassen nicht verstehe. Ich kann das Beispiel aus der Dokumentation kopieren und einfügen, habe aber keine Ahnung, was los ist.

object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
  • Was bedeutet type WeekDay = Valueund warum muss ich das schreiben?
  • Warum ist val Mon = Value? Was bedeutet das überhaupt?
  • Warum muss ich das WeekDay Objekt importieren ? Und,
  • Wenn ich schreibe val day = WeekDay.Mon, warum ist es Typ WeekDay.Value, nicht Typ WeekDay?
Karel Bílek
quelle
2
Ich habe einen kleinen Überblick über Scala-Aufzählung und Alternativen geschrieben. Vielleicht finden Sie ihn nützlich: pedrorijo.com/blog/scala-enums/
pedrorijo91
Versiegelte Merkmale bieten eine hervorragende Alternative - stackoverflow.com/questions/11203268/what-is-a-sealed-trait
Joey Baruch

Antworten:

150

Das EnumerationMerkmal hat ein Typelement, Valuedas die einzelnen Elemente der Aufzählung darstellt (es ist eigentlich eine innere Klasse, aber der Unterschied spielt hier keine Rolle).

Somit object WeekDayerbt, förmigen Bauteils. Die Zeile type WeekDay = Valueist nur ein Typalias . Dies ist nützlich, da Sie diesen import WeekDay._Typ verwenden können, nachdem Sie ihn an eine andere Stelle importiert haben , z.

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

Stattdessen wäre eine minimale Version nur:

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

und Sie müssen nicht müssen den Inhalt importieren object WeekDay, aber dann würden Sie brauchen Typ zu verwenden WeekDay.Valueund die einzelnen Mitglieder zu qualifizieren. So würde das Beispiel werden

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

Die zweite Frage betrifft die Bedeutung von val Mon, ... = Value. Dies ist in der Tat sehr verwirrend, wenn Sie sich nicht mit der Implementierung von befassen Enumeration. Dies ist nicht die Zuordnung eines Typs! Stattdessen wird eine geschützte Methode mit demselben Namen aufgerufen Value, die eine konkrete Instanz vom Typ zurückgibt Value.

So kommt es , dass Sie schreiben können val a, b, c = fooin Scala, und für jeden Wert a, bund cdas Verfahren foowird wieder und wieder aufgerufen werden. EnumerationMit diesem Trick wird ein interner Zähler so erhöht, dass jeder Wert individuell ist.

Wenn Sie die Scala-API-Dokumente für öffnen Enumerationund auf klicken Visibility: All, wird diese Methode angezeigt.

0__
quelle
2
Danke, das ist sehr verwirrend, aber ich denke es ist richtig. Ich werde stattdessen versiegelte Fallklassen verwenden, es scheint 100% einfacher zu sein.
Karel Bílek
2
Ich persönlich bevorzuge auch versiegelte Fallklassen. Ein bisschen ausführlicher, aber weniger Hokus-Pokus mit veränderlichen internen Zählern und so weiter. Mit Scala 2.10 gibt es einige Ideen, wie Aufzählungen (die im Gegensatz zu Java kein Sprachkonstrukt, sondern nur eine Bibliothekslösung sind) mithilfe von Makros besser geschrieben werden können.
0__
@ 0__ Darf ich fragen, warum und wie Sie die versiegelte Klasse verwenden, um die Aufzählung in Scala zu ersetzen? Stimmt etwas mit Scalas Aufzählung nicht?
x1a0
Was ist, wenn Enum-Werte selbst Mitglieder haben? Wie würden Sie beispielsweise die Öffnungszeiten für jeden Wochentag definieren wie: Mo (8,20), ..., So (0,0)?
Simou
1
@simou dann solltest du in der Tat ein versiegeltes Merkmal und tatsächliche Unterklassen verwenden. Ich würde dieses Szenario jedoch kaum als "Aufzählung" bezeichnen. Sie könnten besser schreiben Open(Mon, 8, 20)und die Tage würden eine flache Aufzählung bleiben.
0__