Uma sealed
característica pode ser estendida apenas no mesmo arquivo que sua declaração.
Eles são freqüentemente usados para fornecer uma alternativa para enums
. Como eles podem ser estendidos apenas em um único arquivo, o compilador conhece todos os subtipos possíveis e pode argumentar sobre isso.
Por exemplo, com a declaração:
sealed trait Answer
case object Yes extends Answer
case object No extends Answer
O compilador emitirá um aviso se uma correspondência não for exaustiva:
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
Portanto, você deve usar traços selados (ou classe abstrata selada) se o número de possíveis subtipos for finito e conhecido com antecedência. Para mais exemplos, você pode dar uma olhada nas implementações de lista e opção .
Na medida do possível
sealed
, sim. Eles compartilham as diferenças normais entretrait
eclass
, é claro.Discutível.
Se você tiver um
sealed class X
, precisará verificarX
as subclasses e todas as subclasses. O mesmo não se aplica asealed abstract class X
ousealed trait X
. Então você poderia fazersealed abstract class X
, mas isso é muito mais detalhado do que apenastrait
e com pouca vantagem.A principal vantagem de usar um
abstract class
over atrait
é que ele pode receber parâmetros. Essa vantagem é particularmente relevante ao usar classes de tipo. Digamos que você queira construir uma árvore classificada, por exemplo. Você pode escrever isto:mas você não pode fazer isso:
desde que os limites de contexto (e os limites de exibição) sejam implementados com parâmetros implícitos. Dado que as características não podem receber parâmetros, você não pode fazer isso.
Pessoalmente, prefiro
sealed trait
e uso a menos que alguma razão em particular me faça usar asealed abstract class
. E não estou falando de razões sutis, mas de razões que você não pode ignorar, como o uso de classes de tipo.fonte
[A: F]
) não funciona da mesma maneira que as restrições de variação. Pelo contrário, é o açúcar sintático que exige umF[A]
alcance implícito . Geralmente é usado para convocar instâncias de classe de tipo de uma maneira um pouco mais tensa e mais fácil de ler do que um parâmetro implícito ((implicit fa: F[A])
), mas ainda funciona exatamente da mesma maneira sob o capô e, como Daniel aponta, os traços não conseguem fazer aquele.No blog daily-scala :
fonte
Também sinto a necessidade de apontar as especificações:
fonte
IefBriefly:
e para mais detalhes Tudo sobre traços selados no Scala
fonte