Classe Selada em Kotlin

No tutorial de hoje, estaremos explorando a classe selada em Kotlin. O que são? Qual é o seu uso? Abordaremos todas essas questões abaixo.

Classe Selada em Kotlin

Em termos simples, como o nome sugere, classes seladas são seladas ou fechadas, tornando-as restritas. Classes seladas são usadas para representar hierarquias de classes restritas, em que o objeto ou o valor pode ter valor apenas entre um dos tipos, fixando assim suas hierarquias de tipo. Classes seladas são comumente usadas em casos em que você sabe que um determinado valor deve estar entre um conjunto específico de opções.

Implementando Classes Seladas em Kotlin

As classes seladas em Kotlin são implementadas da seguinte maneira.

sealed class A{
    class B : A()
    class C : A()
}

Para especificar uma classe selada, você precisa adicionar o modificador sealed. Uma classe selada não pode ser instanciada. Portanto, ela é implicitamente abstrata. O seguinte NÃO funcionará.

fun main(args: Array<String>) 
{
    var a = A() //compiler error. Class A cannot be instantiated.
}

Os construtores de uma classe selada são privados por padrão. Todas as subclasses de uma classe selada devem ser declaradas no mesmo arquivo. Classes seladas são importantes para garantir segurança de tipo ao restringir o conjunto de tipos apenas no momento da compilação.

sealed class A{
    class B : A() 
    {
        class E : A() //this works.
    }
    class C : A()

    init {
        println("sealed class A")
    }

}

class D : A() //this works
{
class F: A() //This won't work. Since sealed class is defined in another scope.
}

Criando uma classe selada com construtores.

sealed class A(var name: String){
    class B : A("B")
    class C : A("C")
}

class D : A("D")
fun main(args: Array<String>) {
    
    var b = A.B()
    var d = D()
}

Adicionando a Classe de Dados e o Objeto em uma classe selada.

fun main(args: Array<String>) {

    val e = A.E("Anupam")
    println(e) //prints E(name=Anupam)

    var d = A.D
    d.name() //prints Object D
}


sealed class A{
    class B : A()
    class C : A()
    object D : A()
    {
         fun name()
         {
             println("Object D")
         }
    }
    data class E(var name: String) : A()

}

Diferença entre enum e classes seladas

No Kotlin, as classes seladas podem ser chamadas de classes Enum turbinadas. As classes seladas nos permitem criar instâncias com diferentes tipos, ao contrário dos Enums, que nos restringem a usar o mesmo tipo para todas as constantes enum. O seguinte não é possível em classes Enum.

enum class Months(string: String){
January("Jan"), February(2),
}

Classes Enum permitem apenas um único tipo para todas as constantes. É aqui que as classes seladas vêm em nosso socorro ao permitir várias instâncias.

sealed class Months {
    class January(var shortHand: String) : Months()
    class February(var number: Int) : Months()
    class March(var shortHand: String, var number: Int) : Months()
}

Como você pode usar esse recurso de classes seladas em seus projetos? Em um aplicativo de feed de notícias, você pode criar três tipos de classes diferentes para postagens de Status, Imagem e Vídeo, como mostrado abaixo.

sealed class Post
{
    class Status(var text: String) : Post()
    class Image(var url: String, var caption: String) : Post()
    class Video(var url: String, var timeDuration: Int, var encoding: String): Post()
}

Isso não é possível com classes Enum.

Classes seladas e when

As classes seladas são comumente usadas com instruções when já que cada uma das subclasses e seus tipos funcionam como um caso. Além disso, sabemos que a classe selada limita os tipos. Portanto, a parte else da instrução when pode ser facilmente removida. O exemplo a seguir demonstra o mesmo.

sealed class Shape{
    class Circle(var radius: Float): Shape()
    class Square(var length: Int): Shape()
    class Rectangle(var length: Int, var breadth: Int): Shape()
}

fun eval(e: Shape) =
        when (e) {
            is Shape.Circle -> println("Circle area is ${3.14*e.radius*e.radius}")
            is Shape.Square -> println("Square area is ${e.length*e.length}")
            is Shape.Rectangle -> println("Rectagle area is ${e.length*e.breadth}")
        }

Vamos executar a função eval em nossa função main como mostrado abaixo.

fun main(args: Array) {

    var circle = Shape.Circle(4.5f)
    var square = Shape.Square(4)
    var rectangle = Shape.Rectangle(4,5)

    eval(circle)
    eval(square)
    eval(rectangle)
     //eval(x) // erro de compilação. 

}

 //O seguinte é impresso no console: 
 //Área do círculo é 63.585 
 //Área do quadrado é 16 
 //Área do retângulo é 20 

Observação: O modificador is verifica se a classe é do tipo seguinte. O modificador is é necessário apenas para classes. Não com objetos Kotlin, como mostrado abaixo:

sealed class Shape{
    class Circle(var radius: Float): Shape()
    class Square(var length: Int): Shape()
    object Rectangle: Shape()
    {
        var length: Int = 0
        var breadth : Int = 0
    }
}

fun eval(e: Shape) =
        when (e) {
            is Shape.Circle -> println("Circle area is ${3.14*e.radius*e.radius}")
            is Shape.Square -> println("Square area is ${e.length*e.length}")
            Shape.Rectangle -> println("Rectangle area is ${Shape.Rectangle.length*Shape.Rectangle.breadth}")
        }

Isso encerra o tutorial de classes seladas do Kotlin. Referências: Documentação do Kotlin

Source:
https://www.digitalocean.com/community/tutorials/kotlin-sealed-class