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)