¿Qué es un rasgo sellado?

332

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 usar un rasgo sellado (y cuándo no)?

John Threepwood
fuente

Respuestas:

473

Un sealedrasgo 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 .

paradigmático
fuente
113
Me llevó seis meses llegar al azar aquí y entender cómo reemplazar Java Enum en Scala.
sscarduzio
1
muy agradable ! y no solo finito y conocido de antemano sino también parte de un contexto restringido (¿sellado?) donde tiene sentido verificar todos los subtipos posibles como sí | no, incluso | extraño, etc ...
Mário de Sá Vera
90

un rasgo sellado es lo mismo que una clase sellada?

Hasta donde sealedllega, sí. Comparten las diferencias normales entre traity class, por supuesto.

O, si no, ¿cuáles son las diferencias?

Discutible.

¿Cuándo es una buena idea usar un rasgo sellado (y cuándo no)?

Si tiene un sealed class X, entonces tiene que verificar X, así como cualquier subclase. Lo mismo no es cierto para sealed abstract class Xo sealed trait X. Entonces podría hacerlo sealed abstract class X, pero eso es mucho más detallado que solo traity con poca ventaja.

La principal ventaja de usar un abstract classover a traites 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:

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 hacerlo.

Personalmente, lo prefiero sealed traity lo uso a menos que alguna razón en particular me haga usar a sealed abstract class. Y no estoy hablando de razones sutiles, sino de razones que no puedes ignorar, como usar clases de tipos.

Daniel C. Sobral
fuente
"dado que los límites de contexto (y los límites de vista) se implementan con parámetros implícitos". - ¿Podrías dar más detalles sobre eso?
Ruby
@Ruby: respuesta bastante tardía, pero en caso de que usted o alguien más esté interesado: el límite de contexto ( [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 un F[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.
mirichan
54

Del blog daily-scala :

Cuando un rasgo está "sellado", todas sus subclases se declaran dentro del mismo archivo y eso hace que el conjunto de subclases sea finito, lo que permite ciertas comprobaciones del compilador.

Brian Agnew
fuente
Gracias. ¿Con "todas sus subclases" significa clases y rasgos?
John Threepwood
@ John - No lo he intentado, pero sospecho que hay clases. El punto sobre el sellado es que todo está definido dentro de esa unidad fuente
Brian Agnew,
1
@JohnThreepwood: clases, rasgos y objetos. La mayoría de las veces, en Scala, el término "clase" se usa para referirse a clases, rasgos y objetos. Solo cuando se habla de las diferencias específicas entre ellos, significa solo clases. El SLS usa el término "plantilla" para referirse tanto a las clases como a los rasgos, pero ese término no se usa mucho fuera del SLS, y no hay ningún término que abarque las tres clases, rasgos y objetos.
Jörg W Mittag
7

brevemente:

  • Los rasgos sellados solo se pueden extender en el mismo archivo
  • Listar esto le permite al compilador conocer fácilmente todos los subtipos posibles
  • Use rasgos sellados cuando el número de posibles subtipos es finito y se conoce de antemano
  • Una forma de crear algo como enum en Java
  • Ayuda para definir tipos de datos algebraicos (ADT)

y para más detalles Todo sobre los rasgos sellados en Scala

Majid Hosseini
fuente