Un sealed
rasgo solo se puede extender en el mismo archivo que su declaración.
A menudo se utilizan para proporcionar una alternativa a enums
. Como solo pueden extenderse en un solo archivo, el compilador conoce todos los subtipos posibles y puede razonar al respecto.
Por ejemplo con la declaración:
sealed trait Answer
case object Yes extends Answer
case object No extends Answer
El compilador emitirá una advertencia si una coincidencia no es exhaustiva:
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
Por lo tanto, debe usar rasgos sellados (o clase abstracta sellada) si el número de subtipos posibles es finito y se conoce de antemano. Para obtener más ejemplos, puede echar un vistazo a la lista y las implementaciones de opciones .
Hasta donde
sealed
llega, sí. Comparten las diferencias normales entretrait
yclass
, por supuesto.Discutible.
Si tiene un
sealed class X
, entonces tiene que verificarX
, así como cualquier subclase. Lo mismo no es cierto parasealed abstract class X
osealed trait X
. Entonces podría hacerlosealed abstract class X
, pero eso es mucho más detallado que solotrait
y con poca ventaja.La principal ventaja de usar un
abstract class
over atrait
es que puede recibir parámetros. Esa ventaja es particularmente relevante cuando se usan clases de tipos. Digamos que quieres construir un árbol ordenado, por ejemplo. Puedes escribir esto:pero no puedes hacer esto:
ya que los límites de contexto (y los límites de vista) se implementan con parámetros implícitos. Dado que los rasgos no pueden recibir parámetros, no puedes hacerlo.
Personalmente, lo prefiero
sealed trait
y lo uso a menos que alguna razón en particular me haga usar asealed abstract class
. Y no estoy hablando de razones sutiles, sino de razones que no puedes ignorar, como usar clases de tipos.fuente
[A: F]
) no funciona de la misma manera que las restricciones de varianza. Más bien, es el azúcar sintáctico lo que exige unF[A]
alcance implícito . En general, se usa para convocar instancias de clase de tipo de una manera que es un poco más tersa y más fácil de leer que un parámetro implícito ((implicit fa: F[A])
), pero aún funciona exactamente de la misma manera, y como señala Daniel, los rasgos no llegan a funcionar ese.Del blog daily-scala :
fuente
También siento la necesidad de señalarle las especificaciones:
fuente
brevemente:
y para más detalles Todo sobre los rasgos sellados en Scala
fuente