---
title: "Classes e Objetos em Kotlin Tutorial em Português — Passo a Passo | Kotlin Brasil"
url: "https://kotlin.dev.br/tutoriais/classes-e-objetos-kotlin/"
markdown_url: "https://kotlin.dev.br/tutoriais/classes-e-objetos-kotlin.MD"
description: "Aprenda classes e objetos em Kotlin: construtores, properties, getters/setters, init blocks, companion objects e modificadores de visibilidade."
date: "2025-06-10"
author: "Karina Melo"
---

# Classes e Objetos em Kotlin Tutorial em Português — Passo a Passo | Kotlin Brasil

Aprenda classes e objetos em Kotlin: construtores, properties, getters/setters, init blocks, companion objects e modificadores de visibilidade.


Neste tutorial, vamos explorar em profundidade o sistema de classes e objetos do Kotlin. Programação orientada a objetos (OOP) é um dos paradigmas mais utilizados no desenvolvimento de software, é o Kotlin oferece uma implementação moderna e concisa desses conceitos. Você aprenderá a declarar [classes](/glossario/class/), usar construtores primários e secundários, definir properties com getters e setters personalizados, trabalhar com init blocks, [companion objects](/glossario/companion-object/) e modificadores de visibilidade.

## Declaração de Classes

Em Kotlin, classes são declaradas com a palavra-chave `class`. A forma mais simples de criar uma classe não exige nenhum corpo — apenas o nome é suficiente. Quando a classe possui propriedades e métodos, o corpo é delimitado por chaves.

```kotlin
// Classe vazia (valida em Kotlin)
class Vazio

// Classe com propriedades e metodos
class Pessoa {
    var nome: String = ""
    var idade: Int = 0

    fun apresentar(): String {
        return "Olá, meu nome é $nome e tenho $idade anos."
    }
}

fun main() {
    val pessoa = Pessoa()
    pessoa.nome = "Mariana"
    pessoa.idade = 28
    println(pessoa.apresentar())
    // Olá, meu nome é Mariana e tenho 28 anos.
}
```

Observe que em Kotlin não usamos a palavra-chave `new` para criar instâncias. Basta chamar o nome da classe como uma função. Isso torna a criação de objetos mais limpa e natural.

## Construtor Primário

O construtor primário faz parte da declaração da classe e é colocado logo após o nome. Parâmetros precedidos por `val` ou `var` automaticamente se tornam propriedades da classe, eliminando a necessidade de declaração manual e atribuição no corpo.

```kotlin
class Usuario(
    val nome: String,
    val email: String,
    var ativo: Boolean = true
) {
    fun resumo() = "Usuário: $nome ($email) - Ativo: $ativo"
}

fun main() {
    val user1 = Usuario("Carlos", "carlos@email.com")
    val user2 = Usuario("Ana", "ana@email.com", false)

    println(user1.resumo()) // Usuário: Carlos (carlos@email.com) - Ativo: true
    println(user2.resumo()) // Usuário: Ana (ana@email.com) - Ativo: false

    user1.ativo = false // 'var' permite reatribuição
    // user1.nome = "Outro" // ERRO: 'val' é imutável
}
```

Essa é uma das grandes vantagens do Kotlin sobre o Java: o construtor primário com declaração de propriedades reduz drasticamente o boilerplate. O que em Java exigiria campos privados, construtor e getters/setters, em Kotlin se resolve em poucas linhas.

## Construtor Secundário

Construtores secundários são declarados dentro do corpo da classe usando a palavra-chave `constructor`. Eles devem delegar para o construtor primário, direta ou indiretamente, usando `this()`.

```kotlin
class Produto(val nome: String, val preco: Double) {

    var categoria: String = "Geral"
    var estoque: Int = 0

    // Construtor secundário que delega para o primário
    constructor(nome: String, preco: Double, categoria: String) : this(nome, preco) {
        this.categoria = categoria
    }

    constructor(nome: String, preco: Double, categoria: String, estoque: Int) : this(nome, preco, categoria) {
        this.estoque = estoque
    }

    fun detalhes() = "$nome | R$${"%.2f".format(preco)} | $categoria | Estoque: $estoque"
}

fun main() {
    val p1 = Produto("Teclado", 199.90)
    val p2 = Produto("Mouse", 89.90, "Periféricos")
    val p3 = Produto("Monitor", 1299.00, "Monitores", 15)

    println(p1.detalhes()) // Teclado | R$199.90 | Geral | Estoque: 0
    println(p2.detalhes()) // Mouse | R$89.90 | Periféricos | Estoque: 0
    println(p3.detalhes()) // Monitor | R$1299.00 | Monitores | Estoque: 15
}
```

Na prática, construtores secundários são menos comuns em Kotlin do que em Java, porque default parameters no construtor primário resolvem a maioria dos casos de sobrecarga.

## Properties: Getters e Setters Personalizados

Em Kotlin, toda propriedade tem um getter implícito (e um setter, se for `var`). Você pode personalizar esses acessores para adicionar lógica de válidação ou transformação.

```kotlin
class ContaBancaria(val titular: String, saldoInicial: Double) {

    var saldo: Double = saldoInicial
        private set // setter é privado: só a própria classe altera

    val estaPositiva: Boolean
        get() = saldo > 0 // getter personalizado (calculado a cada acesso)

    var email: String = ""
        set(value) {
            if (value.contains("@")) {
                field = value.lowercase()
            } else {
                println("Email invalido: $value")
            }
        }

    fun depositar(valor: Double) {
        if (valor > 0) saldo += valor
    }

    fun sacar(valor: Double): Boolean {
        return if (valor in 0.01..saldo) {
            saldo -= valor
            true
        } else {
            false
        }
    }
}

fun main() {
    val conta = ContaBancaria("João Silva", 1000.0)
    conta.depositar(500.0)
    println("Saldo: R$${conta.saldo}") // Saldo: R$1500.0
    println("Positiva: ${conta.estaPositiva}") // Positiva: true

    conta.email = "JOAO@Email.COM"
    println("Email: ${conta.email}") // Email: joao@email.com

    conta.email = "invalido" // Email invalido: invalido
}
```

A palavra-chave `field` dentro do setter é o backing field — a referência real ao valor armazenado. Sem ela, atribuir diretamente à propriedade dentro do seu próprio setter causaria uma recursão infinita.

## Init Blocks

O bloco `init` é executado imediatamente após o construtor primário, na ordem em que aparece no corpo da classe. Você pode ter múltiplos blocos `init`, e eles são úteis para válidações e lógica de inicialização.

```kotlin
class Pedido(val cliente: String, val itens: List<String>) {

    val totalItens: Int
    val status: String

    init {
        require(cliente.isNotBlank()) { "Nome do cliente nao pode ser vazio" }
        require(itens.isNotEmpty()) { "Pedido deve ter pelo menos um item" }
        totalItens = itens.size
    }

    init {
        status = if (totalItens > 5) "Grande" else "Normal"
        println("Pedido criado para $cliente com $totalItens itens [$status]")
    }

    fun resumo() = "Pedido de $cliente: ${itens.joinToString(", ")} ($status)"
}

fun main() {
    val pedido = Pedido("Maria", listOf("Arroz", "Feijão", "Café"))
    println(pedido.resumo())
    // Pedido de Maria: Arroz, Feijão, Café (Normal)

    // Isso lançaria IllegalArgumentException:
    // val pedidoInvalido = Pedido("", listOf("Item"))
}
```

Blocos `init` são executados como parte do construtor primário, intercalados com as inicializações de propriedades na ordem em que aparecem no código-fonte.

## Companion Objects

Em Kotlin não existem membros estáticos como em Java. A alternativa é o [companion object](/glossario/companion-object/), um [objeto](/glossario/object/) singleton associado à classe que pode conter propriedades e funções acessíveis pelo nome da classe.

```kotlin
class Configuração private constructor(val ambiente: String, val debug: Boolean) {

    companion object {
        private const val VERSAO = "1.0.0"

        fun desenvolvimento() = Configuração("dev", true)
        fun producao() = Configuração("prod", false)
        fun versao() = VERSAO
    }

    fun info() = "Ambiente: $ambiente | Debug: $debug | Versão: ${versao()}"
}

fun main() {
    val configDev = Configuração.desenvolvimento()
    val configProd = Configuração.producao()

    println(configDev.info())  // Ambiente: dev | Debug: true | Versão: 1.0.0
    println(configProd.info()) // Ambiente: prod | Debug: false | Versão: 1.0.0
    println(Configuração.versao()) // 1.0.0
}
```

Companion objects são frequentemente usados para implementar o padrão Factory Method, como no exemplo acima, onde o construtor é privado e as instâncias são criadas por meio de funções descritivas.

## Modificadores de Visibilidade

Kotlin oferece quatro modificadores de visibilidade que controlam o acesso a classes, funções e propriedades:

```kotlin
class ExemploVisibilidade {
    public val publico = "Acessível de qualquer lugar"       // padrao
    private val privado = "Só dentro desta classe"
    protected val protegido = "Nesta classe e subclasses"
    internal val interno = "Dentro do mesmo módulo"

    private fun metodoPrivado() = "Lógica interna"

    fun metodoPublico(): String {
        // Pode acessar todos os membros
        return "$publico | ${metodoPrivado()}"
    }
}

// Top-level: 'protected' nao é permitido
private fun funcaoPrivadaDoArquivo() = "Visível apenas neste arquivo"
internal fun funcaoInterna() = "Visível no módulo"
```

Em Kotlin, o padrão é `public`, diferente de Java onde o padrão é package-private. O modificador `internal` é único do Kotlin e restringe o acesso ao módulo de compilação, sendo muito útil para bibliotecas que querem esconder detalhes de implementação.

## Erros Comuns

**Esquecer `val` ou `var` no construtor primário.** Parâmetros do construtor sem `val`/`var` não se tornam propriedades da classe. Eles só existem durante a execução do construtor e dos blocos `init`.

```kotlin
// ERRADO: 'nome' nao é propriedade, nao pode ser acessado depois
// class Errada(nome: String) { fun getNome() = nome } // Erro

// CORRETO
class Correta(val nome: String)
```

**Recursão infinita no setter.** Usar o nome da propriedade dentro do seu próprio setter em vez de `field` causa um loop infinito que resulta em StackOverflowError.

**Confundir companion object com instância.** Membros do companion object pertencem à classe, não a instâncias individuais. Tentar acessar propriedades de instância dentro do companion object causa erro de compilação.

**Ignorar `init` order.** Propriedades e blocos `init` são executados na ordem em que aparecem. Referenciar uma propriedade antes de sua declaração pode resultar em valores inesperados ou nulos.

## Conclusão e Próximos Passos

Neste tutorial, você dominou os fundamentos de classes e objetos em Kotlin: declaração de classes, construtores primários e secundários, properties com getters e setters customizados, blocos `init`, companion objects e modificadores de visibilidade. Esses conceitos formam a base da programação orientada a objetos em Kotlin.

O próximo passo é aprender sobre [herança em Kotlin](/tutoriais/heranca-kotlin/), onde você verá como criar hierarquias de classes usando `open`, `override` e classes [abstratas](/glossario/abstract/). Também recomendamos estudar [data classes](/glossario/data-class/), que geram automaticamente `equals()`, `hashCode()`, `toString()` e `copy()`. Com o domínio de classes e objetos, você está pronto para construir aplicações Kotlin bem estruturadas e de fácil manutenção.
