Recursos Sintáticos Específicos do Kotlin

Valor principal: Simplificam a definição de modelos de dados, gerando métodos comuns automaticamente.

// Definição de uma data class
data class Produto(
    val codigo: Int,
    val nome: String,
    val preco: Double,
    val estoque: Int = 0  // Valor padrão
)

// Criação de instâncias
val item1 = Produto(101, "Livro A", 29.99, 15)
val item2 = Produto(102, "Livro B", 39.99, 10)

// toString() gerado automaticamente
println(item1) // Saída: Produto(codigo=101, nome=Livro A, preco=29.99, estoque=15)

// equals() e hashCode() gerados automaticamente
val item3 = Produto(101, "Livro A", 29.99, 15)
println(item1 == item3) // Saída: true (comparação por valor)

// Método copy() - cria cópia com alterações parciais
val item4 = item1.copy(estoque = 20)
println(item4) // Saída: Produto(codigo=101, nome=Livro A, preco=29.99, estoque=20)

// Declaração de desestruturação
val (id, titulo, valor, quantidade) = item1
println("Código: $id, Nome: $titulo, Preço: $valor, Estoque: $quantidade")

Cenários de uso para data classes:

  • Modelos de dados para respostas de API
  • Entidades de banco de dados
  • Objetos de configuração
  • Qualquer classe que apenas armazene dados

Valor principal: Representam uma hieraruqia de classes restrita, onde o compilador conhece todas as subclasses.

// Definição de uma sealed class
sealed class Resposta

data class Sucesso(val dados: String) : Resposta()
data class Falha(val mensagemErro: String) : Resposta()
object Carregando : Resposta() // Objeto singleton

// Uso com expressão when (conversão inteligente)
fun processarResposta(resultado: Resposta) {
    when (resultado) {
        is Sucesso -> println("Sucesso: ${resultado.dados}")
        is Falha -> println("Erro: ${resultado.mensagemErro}")
        is Carregando -> println("Carregando...")
        // Não necessita de cláusula else, pois o compilador sabe todas as possibilidades
    }
}

// Exemplos de uso
val resposta1: Resposta = Sucesso("Dados carregados com sucesso")
processarResposta(resposta1) // Saída: Sucesso: Dados carregados com sucesso

val resposta2: Resposta = Falha("Falha na conexão de rede")
processarResposta(resposta2) // Saída: Erro: Falha na conexão de rede

val resposta3: Resposta = Carregando
processarResposta(resposta3) // Saída: Carregando...

Cenários de uso para sealed classes:

  • Representação de estados finitos (ex.: estados da interface do usuário)
  • Tratamento de resultados de solicitações de rede
  • Definição de sistemas de tipos restritos
  • Correspondência de padrões em expressões

Singleton object:

// Objeto singleton
object ConfigBancoDados {
    const val NOME_BANCO = "meu_aplicativo.db"
    const val VERSAO_BANCO = 1

    fun obterConexao(): String {
        return "jdbc:sqlite:$NOME_BANCO"
    }
}

// Uso
ConfigBancoDados.obterConexao() // Saída: jdbc:sqlite:meu_aplicativo.db
ConfigBancoDados.NOME_BANCO // Saída: meu_aplicativo.db

Companion object:

class FabricaPessoa {
    companion object {
        private const val IDADE_PADRAO = 18

        fun criar(nome: String): Pessoa {
            return Pessoa(0, nome, "", IDADE_PADRAO)
        }

        fun criarComId(id: Int, nome: String): Pessoa {
            return Pessoa(id, nome, "", IDADE_PADRAO)
        }
    }
}

// Uso (chamada similar a métodos estáticos em Java)
val pessoa1 = FabricaPessoa.criar("Ana")
val pessoa2 = FabricaPessoa.criarComId(5, "Carlos")

Object expressions (substituto para classes anônimas):

// Classe anônima no estilo Java
button.setOnClickListener(object : OnClickListener {
    override fun onClick(view: View) {
        println("Botão clicado")
    }
})

// Expressão lambda (mais concisa)
button.setOnClickListener { view ->
    println("Botão clicado")
}

// Conversão SAM (Single Abstract Method)
button.setOnClickListener { println("Botão clicado") }

Valor principal: Adicionar novos métodos a classes sem mdoificar sua implementação oirginal.

// Função de extensão
fun String.primeiroCaractere(): Char {
    return this[0]
}

// Uso
val texto = "Kotlin"
println(texto.primeiroCaractere()) // Saída: K

// Propriedade de extensão
val String.indiceFinal: Int
    get() = this.length - 1

// Uso
println("Olá".indiceFinal) // Saída: 2

// Funções de extensão para View no Android
fun View.esconder() {
    this.visibility = View.GONE
}

fun View.mostrar() {
    this.visibility = View.VISIBLE
}

fun View.tornarInvisivel() {
    this.visibility = View.INVISIBLE
}

// Uso
textView.esconder()
button.mostrar()

Aplicações práticas:

// Função de extensão para formatação de datas
fun Date.formatarParaString(): String {
    val formato = SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.getDefault())
    return formato.format(this)
}

// Uso
val dataAtual = Date()
println(dataAtual.formatarParaString())

// Função de extensão para simplificar operações com SharedPreferences
fun SharedPreferences.salvarBoolean(chave: String, valor: Boolean) {
    edit().putBoolean(chave, valor).apply()
}

fun SharedPreferences.obterBoolean(chave: String, padrao: Boolean): Boolean {
    return getBoolean(chave, padrao)
}

// Uso
val prefs = getSharedPreferences("configuracoes", Context.MODE_PRIVATE)
prefs.salvarBoolean("autenticado", true)
val autenticado = prefs.obterBoolean("autenticado", false)

Tags: Kotlin data-class sealed-class singleton extension-function

Publicado em 6-11 06:29 por Thomas