Cos’è un tratto sigillato?

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

Mi piacerebbe sapere se un tratto sigillato è uguale a una class sigillata? Oppure, se no, quali sono le differenze? Quando è una buona idea usare un tratto sigillato (e quando no)?

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

Sono spesso usati per fornire un’alternativa alle 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") | } :12: warning: match is not exhaustive! missing combination Yes 

Quindi dovresti usare tratti sigillati (o classi astratte sigillate) se il numero di possibili sottotipi è finito e noto in anticipo. Per ulteriori esempi è ansible dare un’occhiata alle implementazioni di elenchi e opzioni .

un tratto sigillato è lo stesso di una class sigillata?

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

Oppure, se no, quali sono le differenze?

Moot.

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

Se hai una sealed class X , devi controllare X e tutte le sottoclassi. Lo stesso non vale per la sealed abstract class X o per il sealed trait X Quindi potresti fare una sealed abstract class X , ma è molto più verbosa che semplice e per un piccolo vantaggio.

Il vantaggio principale dell’uso di una abstract class su un trait è che può ricevere parametri. Questo vantaggio è particolarmente rilevante quando si usano classi di tipi. Supponiamo che tu voglia build un albero ordinato, ad 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 limiti di vista) sono implementati con parametri impliciti. Dato che i tratti non possono ricevere parametri, non puoi farlo.

Personalmente, preferisco il sealed trait e lo uso a meno che qualche particolare motivo mi faccia usare una 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.

Dal blog della scala quotidiana :

Quando un tratto è “sigillato”, tutte le sue sottoclassi vengono dichiarate all’interno dello stesso file e ciò rende l’insieme di sottoclassi finito che consente determinati controlli del compilatore.

Inoltre sento il bisogno di indicarti le specifiche:

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

– M. Odersky. Le specifiche della lingua di Scala, versione 2.8. online, settembre 2013.

brevemente:

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

e per maggiori dettagli Tutto sui tratti sigillati in Scala