Les classes scellées sont décrites dans "Programmation en Scala", mais les traits scellés ne le sont pas. Où puis-je trouver plus d'informations sur un trait scellé?
Je voudrais savoir si un trait scellé est identique à une classe scellée? Ou, sinon, quelles sont les différences? Quand est-ce une bonne idée d'utiliser un trait scellé (et quand non)?
Un trait sealed
ne peut être étendu que dans le même fichier que sa déclaration.
Ils sont souvent utilisés pour fournir une alternative à enums
. Comme ils ne peuvent être étendus que dans un seul fichier, le compilateur connaît tous les sous-types possibles et peut raisonner à ce sujet.
Par exemple avec la déclaration:
sealed trait Answer
case object Yes extends Answer
case object No extends Answer
Le compilateur émettra un avertissement si une correspondance n'est pas exhaustive:
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
Vous devez donc utiliser des traits scellés (ou une classe abstraite scellée) si le nombre de sous-types possibles est fini et connu à l'avance. Pour plus d'exemples, vous pouvez consulter les implémentations de liste et option .
un trait scellé est-il identique à une classe scellée?
En ce qui concerne sealed
, oui. Ils partagent les différences normales entre trait
et class
, bien sûr.
Ou, sinon, quelles sont les différences?
Discutable.
Quand est-ce une bonne idée d'utiliser un trait scellé (et quand non)?
Si vous avez un sealed class X
, vous devez alors vérifier X
ainsi que toutes les sous-classes. Il n'en va pas de même pour sealed abstract class X
ou sealed trait X
. Vous pouvez donc faire sealed abstract class X
, mais c'est beaucoup plus verbeux que trait
et pour peu d'avantages.
Le principal avantage de l'utilisation d'un abstract class
par-dessus un trait
est qu'il peut recevoir des paramètres. Cet avantage est particulièrement pertinent lors de l'utilisation de classes de types. Disons que vous voulez construire un arbre trié, par exemple. Vous pouvez écrire ceci:
sealed abstract class Tree[T : Ordering]
mais vous ne pouvez pas faire ceci:
sealed trait Tree[T : Ordering]
puisque les limites de contexte (et les limites de vue) sont implémentées avec des paramètres implicites. Étant donné que les traits ne peuvent pas recevoir de paramètres, vous ne pouvez pas le faire.
Personnellement, je préfère sealed trait
et je l’utilise sauf si une raison particulière me fait utiliser un sealed abstract class
. Et je ne parle pas de raisons subtiles, mais de raisons que vous ne pouvez pas ignorer, telles que l’utilisation de classes de types.
De la daily-scala blog :
Lorsqu'un trait est "scellé", toutes ses sous-classes sont déclarées dans le même fichier, ce qui rend l'ensemble des sous-classes fini, ce qui permet certaines vérifications du compilateur.
Aussi, je ressens le besoin de vous indiquer les spécifications:
Le modificateur scellé s'applique aux définitions de classe. Une classe scellée peut ne pas être directement héritée, sauf si le modèle hérité est défini dans le même fichier source que la classe héritée. Cependant, les sous-classes d'une classe scellée peuvent être héritées n'importe où.
- M. Odersky. Spécification du langage Scala, version 2.8. En ligne, septembre 2013.
brièvement:
et pour plus de détails Tout sur les traits scellés en Scala