web-dev-qa-db-fra.com

Qu'est-ce qu'un trait scellé?

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)?

319
John Threepwood

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 .

446
paradigmatic

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.

87
Daniel C. Sobral

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.

52
Brian Agnew

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.

27
A T

brièvement:

  • Les traits scellés ne peuvent être étendus que dans le même fichier
  • La liste permet au compilateur de connaître facilement tous les sous-types possibles
  • Utilisez des traits scellés lorsque le nombre de sous-types possibles est fini et connu à l'avance
  • Une façon de créer quelque chose comme enum en Java
  • Aide à la définition de types de données algébriques (ADT)

et pour plus de détails Tout sur les traits scellés en Scala

3
Majid Hosseini