Ein sealed
Merkmal kann nur in derselben Datei wie seine Deklaration erweitert werden.
Sie werden oft verwendet, um eine Alternative zu bieten enums
. Da sie nur in einer einzigen Datei erweitert werden können, kennt der Compiler alle möglichen Untertypen und kann darüber nachdenken.
Zum Beispiel mit der Erklärung:
sealed trait Answer
case object Yes extends Answer
case object No extends Answer
Der Compiler gibt eine Warnung aus, wenn eine Übereinstimmung nicht vollständig ist:
scala> val x: Answer = Yes
x: Answer = Yes
scala> x match {
| case No => println("No")
| }
<console>:12: warning: match is not exhaustive!
missing combination Yes
Sie sollten also versiegelte Merkmale (oder versiegelte abstrakte Klassen) verwenden, wenn die Anzahl der möglichen Untertypen endlich und im Voraus bekannt ist. Weitere Beispiele finden Sie in den Implementierungen von Listen und Optionen .
Soweit
sealed
ja. Sie teilen natürlich die normalen Unterschiede zwischentrait
undclass
.Moot.
Wenn Sie eine haben
sealed class X
, müssen Sie nachX
Unterklassen suchen. Das gleiche gilt nicht fürsealed abstract class X
odersealed trait X
. Sie könnten es also tunsealed abstract class X
, aber das ist viel ausführlicher als nurtrait
und für wenig Vorteil.Der Hauptvorteil der Verwendung von a
abstract class
über atrait
besteht darin, dass Parameter empfangen werden können. Dieser Vorteil ist besonders relevant bei der Verwendung von Typklassen. Angenommen, Sie möchten beispielsweise einen sortierten Baum erstellen. Sie können dies schreiben:aber du kannst das nicht tun:
da Kontextgrenzen (und Ansichtsgrenzen) mit impliziten Parametern implementiert werden. Da Merkmale keine Parameter empfangen können, können Sie dies nicht tun.
Persönlich bevorzuge
sealed trait
und benutze ich es , es sei denn, ein bestimmter Grund zwingt mich dazu, a zu verwendensealed abstract class
. Und ich spreche nicht über subtile Gründe, sondern über Gründe, die Sie nicht ignorieren können, z. B. die Verwendung von Typklassen.quelle
[A: F]
) funktioniert nicht so wie Varianzbeschränkungen. Vielmehr ist es syntaktischer Zucker, der einen implizitenF[A]
Umfang erfordert . Es wird im Allgemeinen verwendet, um Instanzen von Typklassen auf eine Weise zu beschwören, die etwas knapper und leichter zu lesen ist als ein impliziter Parameter ((implicit fa: F[A])
), aber es funktioniert unter der Haube immer noch genauso, und wie Daniel betont, können Merkmale nicht funktionieren Das.Aus dem Daily-Scala-Blog :
quelle
Ich habe auch das Bedürfnis, Sie auf die Spezifikationen hinzuweisen:
quelle
kurz:
und für weitere Details Alles über versiegelte Merkmale in Scala
quelle