Che cos'è un tratto sigillato?


332

Le classi sigillate sono descritte in "Programmazione in Scala", mentre i tratti sigillati no. Dove posso trovare ulteriori informazioni su un tratto sigillato?

Vorrei sapere se un tratto sigillato è uguale a una classe sigillata? O, in caso contrario, quali sono le differenze? Quando è una buona idea usare un tratto sigillato (e quando no)?

Risposte:


473

UN sealed tratto può essere esteso solo nello stesso file della sua dichiarazione.

Sono spesso usati per fornire un'alternativa a enums . Poiché possono essere estesi solo in un singolo file, il compilatore conosce tutti i possibili sottotipi e può ragionare su di esso.

Ad esempio con la dichiarazione:

sealed trait Answer
case object Yes extends Answer
case object No extends Answer

Il compilatore emetterà un avviso se una corrispondenza non è esaustiva:

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

Quindi dovresti usare tratti sigillati (o classe astratta sigillata) se il numero di sottotipi possibili è finito e noto in anticipo. Per altri esempi puoi dare un'occhiata all'elenco e alle implementazioni delle opzioni .


113
mi ci sono voluti sei mesi per arrivare a caso qui e capire come sostituire Java Enum in Scala.
sscarduzio,

1
molto bella ! e non solo finito e conosciuto in anticipo, ma anche parte di un contesto ristretto (sigillato?) in cui ha senso controllare tutti i possibili sottotipi come yes | no, anche | strano ecc ...
Mário de Sá Vera

90

un tratto sigillato è uguale a una classe sigillata?

Per quanto riguarda sealed, sì. Condividono le normali differenze tra traite class, ovviamente.

O, in caso contrario, quali sono le differenze?

Moot.

Quando è una buona idea usare un tratto sigillato (e quando no)?

Se si dispone di una sealed class X, è necessario verificare la presenza di Xeventuali sottoclassi. Lo stesso non vale per sealed abstract class Xo sealed trait X. Quindi potresti farlo sealed abstract class X, ma è molto più prolisso che solotrait e per poco vantaggio.

Il vantaggio principale dell'utilizzo di un abstract classover a traitè che può ricevere parametri. Tale vantaggio è particolarmente rilevante quando si utilizzano le classi di tipi. Supponiamo che tu voglia costruire un albero ordinato, per esempio. Puoi scrivere questo:

sealed abstract class Tree[T : Ordering]

ma non puoi farlo:

sealed trait Tree[T : Ordering]

poiché i limiti di contesto (e i limiti di visualizzazione) sono implementati con parametri impliciti. Dato che i tratti non possono ricevere parametri, non puoi farlo.

Personalmente, preferisco sealed traite lo uso a meno che qualche motivo particolare non mi faccia usare a sealed abstract class. E non sto parlando di ragioni impercettibili, ma di ragioni che non puoi ignorare, come usare le classi di tipo.


"poiché i limiti di contesto (e i limiti di visualizzazione) sono implementati con parametri impliciti." - potresti approfondire questo?
Ruby,

@Ruby - risposta abbastanza tardi, ma nel caso tu o qualcun altro sia interessato: il bounding del contesto ( [A: F]) non funziona allo stesso modo dei vincoli di varianza. Piuttosto, è lo zucchero sintattico che richiede una F[A]portata implicita . Viene generalmente utilizzato per convocare istanze di typeclass in un modo un po 'più terso e più facile da leggere rispetto a un parametro implicito ( (implicit fa: F[A])), ma funziona sempre allo stesso modo sotto il cofano e, come sottolinea Daniel, i tratti non riescono a fare quello.
mirichan,

54

Dal blog di scala quotidiana :

Quando un tratto viene "sigillato", tutte le sue sottoclassi vengono dichiarate all'interno dello stesso file e ciò rende finito l'insieme di sottoclassi che consente alcuni controlli del compilatore.


Grazie. Con "tutte le sue sottoclassi" significa classi e tratti?
John Threepwood,

@John - Non ho provato, ma sospetto che le lezioni. Il punto sul suggellamento è che tutto è definito all'interno di quell'unità sorgente
Brian Agnew, il

1
@JohnThreepwood: classi, tratti e oggetti. Il più delle volte, a Scala, il termine "classe" è usato per riferirsi a classi, tratti e oggetti. Solo quando si parla delle differenze specifiche tra loro, significa solo classi. SLS usa il termine "modello" per riferirsi sia a classi che a tratti, ma quel termine non è usato molto al di fuori di SLS e non esiste un termine che comprenda tutte e tre le classi, i tratti e gli oggetti.
Jörg W Mittag,

30

Inoltre sento la necessità di indicarti le specifiche:

Il modi fi catore sigillato si applica alle definizioni di classe. Una classe sigillata non può essere ereditata direttamente, tranne se il modello ereditario è definito nello stesso file di origine della classe ereditata. Tuttavia, le sottoclassi di una classe sigillata possono essere ereditate ovunque.

- M. Odersky. Le specifiche del linguaggio Scala, versione 2.8. online, settembre 2013.


7

brevemente:

  • I tratti sigillati possono essere estesi solo nello stesso file
  • Elenco che consente al compilatore di conoscere facilmente tutti i possibili sottotipi
  • Usa tratti sigillati quando il numero dei possibili sottotipi è finito e noto in anticipo
  • Un modo di creare qualcosa come enum in Java
  • Aiuta a definire i tipi di dati algebrici (ADT)

e per maggiori dettagli Tutto sui tratti sigillati di Scala

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.