2012-06-26 21 views
264

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

Mi piacerebbe sapere, se un tratto sigillato è lo stesso di una classe sigillata? Oppure, se no, quali sono le differenze? Quando è una buona idea usare un tratto sigillato (e quando no)?

risposta

42

Dal daily-scala blog:

Quando un tratto è "sigillato" tutte le sue sottoclassi sono dichiarati all'interno dello stesso file e che rende l'insieme di sottoclassi finite che permette alcuni controlli del compilatore.

+0

Grazie. Con "tutte le sue sottoclassi" significa classi e tratti? –

+1

Downvoted perché? –

+0

@ John - Non ho provato, ma sospetto le lezioni. Il punto sulla sigillatura è che tutto è definito all'interno di quell'unica unità sorgente –

354

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

Sono spesso utilizzati 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.

Per esempio con la dichiarazione:

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

Il compilatore emetterà un avviso se una partita non è esaustivo:

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 

tratti Così si dovrebbe usare sigillati (o classe astratta sigillato) se il numero di possibili sottotipi è finito e noto in anticipo. Per ulteriori esempi è possibile dare un'occhiata alle implementazioni list e option.

+78

mi ci sono voluti sei mesi per arrivare casualmente qui e capire come sostituire Java Enum in Scala. – sscarduzio

77

un tratto sigillato è lo stesso di una classe sigillata?

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

Oppure, in caso contrario, quali sono le differenze?

Moot.

Quando è consigliabile utilizzare un tratto sigillato (e quando non lo è)?

Se si dispone di un sealed class X, poi si deve verificare la presenza di X così come qualsiasi sottoclassi. Lo stesso non è vero per sealed abstract class X o sealed trait X. Quindi potresti fare sealed abstract class X, ma è molto più verboso del solo trait e per un piccolo vantaggio.

Il vantaggio principale dell'utilizzo di abstract class su un trait è che può ricevere parametri. Questo vantaggio è particolarmente rilevante quando si usano classi di tipi. Supponiamo che tu voglia costruire un albero ordinato, ad esempio.È possibile scrivere questo:

sealed abstract class Tree[T : Ordering] 

, ma non si può fare questo:

sealed trait Tree[T : Ordering] 

dal limite di contesto (e visualizzare i limiti) sono implementate con i parametri impliciti. Dato che i tratti non possono ricevere parametri, non puoi farlo.

Personalmente, preferisco sealed trait e lo uso a meno che qualche motivo particolare mi faccia usare un sealed abstract class. E non sto parlando di ragioni impercettibili, ma di ragioni in-faccia che non puoi ignorare, come usare le classi di tipi.

+0

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

22

Anche io sento il bisogno di indicare le specifiche che avete:

Il sigillato modi fi catore si applica alla classe di de fi nizioni. Una classe sigillata non può essere ereditata direttamente, tranne se il modello ereditario è definito nella stessa sorgente come classe ereditata. Tuttavia, le sottoclassi di una classe sigillata possono essere ereditate ovunque.

- M. Odersky. The Scala language specification, version 2.8. online, Sept., 2013.

Problemi correlati