¿Qué es un rasgo sellado?
Las clases selladas se describen en 'Programación en Scala', pero los rasgos sellados no. ¿Dónde puedo encontrar más información sobre un rasgo sellado?
Me gustaría saber si un rasgo sellado es lo mismo que una clase sellada. O, si no, ¿cuáles son las diferencias? ¿Cuándo es una buena idea utilizar un rasgo sellado (y cuándo no)?
Un sealed
rasgo se puede extender sólo en el mismo archivo que su declaración.
A menudo se utilizan para proporcionar una alternativa a enums
. Dado que sólo se pueden ampliar en un único 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, debería utilizar rasgos sellados (o clases abstractas selladas) si el número de subtipos posibles es finito y se conoce de antemano. Para obtener más ejemplos, puede consultar la lista y las implementaciones de opciones .
¿Un rasgo sellado es lo mismo que una clase sellada?
Hasta donde sealed
llega, sí. Comparten las diferencias normales entre trait
y class
, por supuesto.
O, si no, ¿cuáles son las diferencias?
Discutible.
¿Cuándo es una buena idea utilizar un rasgo sellado (y cuándo no)?
Si tiene un sealed class X
, debe verificar X
también las subclases. No ocurre lo mismo con sealed abstract class X
o sealed trait X
. Entonces podrías hacerlo sealed abstract class X
, pero eso es mucho más detallado que solo trait
y con poca ventaja.
La principal ventaja de utilizar un abstract class
sobre a trait
es que puede recibir parámetros. Esa ventaja es particularmente relevante cuando se utilizan clases de tipos. Digamos que quieres construir un árbol ordenado, por ejemplo. Puedes escribir esto:
sealed abstract class Tree[T : Ordering]
pero no puedes hacer esto:
sealed trait Tree[T : Ordering]
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 hacer eso.
Personalmente, lo prefiero sealed trait
y lo uso a menos que alguna razón en particular me obligue a usar un archivo sealed abstract class
. Y no me refiero a razones sutiles, sino a razones directas que no puedes ignorar, como el uso de clases de tipos.