Classes seladas em Kotlin

Classes seladas em Kotlin

1. Introdução

Simplificando, a linguagem Kotlin emprestou vários conceitos de outras linguagens funcionais para ajudar a escrever código mais seguro e legível. Hierarquias seladas é um desses conceitos.

2. O que é uma classe selada?

Classes seladas nos permitem corrigir hierarquias de tipo e proíbem os desenvolvedores de criar novas subclasses.

Eles são úteis quando você possui uma hierarquia de herança muito rigorosa, com um conjunto específico de subclasses possíveis e sem outras. The compiler guarantees that only classes defined in the same source file as the sealed class are able to inherit from it.

As classes seladas também são implicitamenteabstract. Eles devem ser tratados como tal por todo o resto do seu código, exceto que nada mais pode implementá-los.

Classes seladas podem ter campos e métodos definidos nelas, incluindo funções abstratas e implementadas. Isso significa que você pode ter uma representação básica da classe e ajustá-la para se adequar às subclasses.

3. Quando usar classes seladas?

Sealed classes are designed to be used when there are a very specific set of possible options para um valor, e onde cada uma dessas opções é funcionalmente diferente - apenasAlgebraic Data Types.

Casos de uso comuns podem incluir a implementação deState Machine ou emMonadic Programming, que está se tornando cada vez mais popular com o advento dos conceitos de programação funcional.

Sempre que você tiver várias opções e elas diferirem apenas no significado dos dados, será melhor usarEnum Classes.

Sempre que você tiver um número desconhecido de opções, não poderá usar uma classe selada, pois isso impedirá a adição de opções fora do arquivo de origem original.

4. Escrevendo aulas seladas

Vamos começar escrevendo nossa própria classe lacrada - o bom exemplo dessa hierarquia lacrada é umOptional do Java 8 - que pode serSome ouNone.

Ao implementar isso, faz muito sentido restringir a possibilidade de criar novas implementações - as duas implementações fornecidas são exaustivas e ninguém deve adicionar suas próprias.

Como tal, podemos implementar isso:

sealed class Optional {
    // ...
    abstract fun isPresent(): Boolean
}

data class Some(val value: V) : Optional() {
    // ...
    override fun isPresent(): Boolean = true
}

class None : Optional() {
    // ...
    override fun isPresent(): Boolean = false
}

Agora pode ser garantido que sempre que você tiver uma instância deOptional<V>, você realmente terá umSome<V> ou um<V> Nenhum.

No Java 8, a implementação real parece diferente devido à ausência de classes lacradas.

Podemos então fazer uso disso em nossos cálculos:

val result: Optional = divide(1, 0)
println(result.isPresent())
if (result is Some) {
    println(result.value)
}

A primeira linha retornaráSome ouNone. Em seguida, produzimos se obtivemos ou não um resultado.

5. Use com quando

Kotlin tem suporte para o uso de classes seladas em suas construçõeswhen. Porque sempre há um conjunto exato de subclasses possíveis,the compiler is able to warn you if any branch is not handled, in exactly the same way that it does for enumerations.

Isso significa que em tais situações, normalmente não há necessidade de um manipulador pega-tudo, o que por sua vez significa que adicionar uma nova subclasse é automaticamente seguro - o compilador irá avisá-lo imediatamente se você não tiver feito isso, e você precisará para corrigir esses erros antes de continuar.

O exemplo acima pode ser estendido para gerar o resultado ou um erro, dependendo do tipo retornado:

val message = when (result) {
    is Some -> "Answer: ${result.value}"
    is None -> "No result"
}
println(message)

Se um dos dois ramos estiver ausente, isso não será compilado e resultará em um erro de:

'when' expression must be exhaustive, add necessary 'else' branch

6. Sumário

Classes seladas podem ser uma ferramenta valiosa para sua caixa de ferramentas de design de API. Permitir uma hierarquia de classes bem conhecida e estruturada que possa ser apenas um de um conjunto esperado de classes pode ajudar a remover todo um conjunto de possíveis condições de erro do seu código, além de facilitar a leitura e a manutenção.

Como sempre, trechos de código podem ser encontradosover on GitHub.