Public get, private set em Kotlin: como não pisar na bola (e o que fazer se já pisou)
\n\nOlá, colega! Se você já pesquisou "Kotlin public get private set var" no Google, não está sozinho. Essa consulta é um verdadeiro sucesso no Stack Overflow, e milhares de desenvolvedores (incluindo eu, no passado) bateram a cabeça no teclado tentando entender por que seu código não funcionava.
\n\nParece simples, não? Quero que a propriedade seja acessível a todos (public get), mas apenas a própria classe possa modificá-la (private set). Em Java, era rotina: declarar um campo private, escrever um getter e um setter, e tornar o setter privado. Em Kotlin, tudo deveria ser mais fácil, mas...
\n\nSpoiler: a sintaxe existe, mas nem sempre funciona como você espera. Neste artigo, vamos analisar os principais erros que até desenvolvedores experientes cometem e mostrar como evitá-los. Vamos lá!
\n\nAnatomia de uma propriedade: var, val, get e set
\n\nPara começar, uma rápida introdução. Em Kotlin, propriedades (properties) não são apenas campos. São elementos completos que podem conter getters e setters. Aqui está a estrutura básica:
\n\nvar nome_da_propriedade: Tipo = valor_padrao\n get() = field\n set(value) { field = value }\n\nSe você usa var, o Kotlin gera automaticamente um getter e um setter. Mas você pode substituir o comportamento deles. E também pode alterar a visibilidade deles (visibility modifiers: public, private, internal, protected).
E é aqui que a coisa fica interessante. Para tornar o getter público e o setter privado, você precisa escrever:
\n\nvar name: String = "default"\n private set\n\nSó isso? Quase. Mas existem nuances que quebram esse mecanismo.
\n\nErro nº 1: Esquecer o construtor
\n\nO problema mais comum é tentar declarar public get private set var no construtor da classe. Por exemplo:
// ❌ Erro: não é permitido\nclass User(public get private set var name: String)\n\nO Kotlin emitirá um erro de compilação. Por quê? Porque os parâmetros do construtor não são propriedades. São apenas parâmetros. Se você quer que uma propriedade tenha a visibilidade do setter alterada, ela deve ser declarada no corpo da classe.
\n\nComo fazer corretamente:
\n\nclass User(name: String) {\n var name: String = name\n private set\n}\n\nOu, se estiver usando data class, terá que dar um jeito:
data class User(private val _name: String) {\n var name: String = _name\n private set\n}\n\nSim, o data class não permite alterar a visibilidade do setter diretamente para propriedades do construtor primário. Você precisará usar um backing field.
Erro nº 2: Confusão com backing field
\n\nBacking field é um campo oculto que o Kotlin gera automaticamente para uma propriedade se você usar field no getter ou setter. Mas se você substituir o getter ou setter sem referenciar field, o backing field não será criado.
Exemplo do problema:
\n\nvar counter: Int = 0\n private set\n get() = field * 2 // ❌ Erro: field não definido\n\nNão, isso não é um erro de compilação. Mas se você escrever:
\n\nvar counter: Int = 0\n private set\n get() = 42 // tudo ok, mas field não é usado\n\nNeste caso, o backing field não será criado. E se você tentar acessar field no setter, receberá um erro. A boa notícia: se você usar private set, o backing field quase sempre é criado automaticamente, porque o setter padrão usa field. Mas se você substituir o setter sem field — prepare-se para surpresas.
Dica: sempre use field explicitamente no getter e setter se quiser trabalhar com o backing field. E lembre-se: se a propriedade não tiver um backing fie