Public get private set en Kotlin: trampas y soluciones

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Public get, private set en Kotlin: cómo no pisar el rastrillo (y qué hacer si ya lo pisaste)

\n\n

¡Hola, colega! Si alguna vez has buscado en Google "Kotlin public get private set var", no estás solo. Esta consulta es un verdadero éxito en Stack Overflow, y miles de desarrolladores (incluyéndome a mí en su momento) se golpearon la cabeza contra el teclado tratando de entender por qué su código no funcionaba.

\n\n

¿Parece sencillo, verdad? Quiero que la propiedad sea accesible para todos (public get), pero que solo la clase pueda modificarla (private set). En Java era rutina: declarabas un campo private, escribías un getter y un setter, y hacías el setter privado. En Kotlin todo debería ser más simple, pero...

\n\n

Spoiler: la sintaxis existe, pero no siempre funciona como esperas. En este artículo, analizaremos los principales errores que cometen incluso los desarrolladores experimentados y mostraremos cómo evitarlos. ¡Allá vamos!

\n\n

Anatomía de una propiedad: var, val, get y set

\n\n

Para empezar, un repaso rápido. En Kotlin, las propiedades no son solo campos. Son elementos completos que pueden contener getters y setters. Esta es la estructura básica:

\n\n
var nombre_propiedad: Tipo = valor_por_defecto\n    get() = field\n    set(value) { field = value }
\n\n

Si usas var, Kotlin genera automáticamente un getter y un setter. Pero puedes sobrescribir su comportamiento. Y también puedes cambiar su visibilidad (modificadores de visibilidad: public, private, internal, protected).

\n\n

Y aquí es donde se pone interesante. Para hacer el getter público y el setter privado, debes escribir:

\n\n
var name: String = "default"\n    private set
\n\n

¿Eso es todo? Casi. Pero hay matices que rompen este mecanismo.

\n\n

Error n.º 1: Olvidar el constructor

\n\n

El problema más común es intentar declarar public get private set var en el constructor de la clase. Por ejemplo:

\n\n
// ❌ Error: no se puede hacer así\nclass User(public get private set var name: String)
\n\n

Kotlin mostrará un error de compilación. ¿Por qué? Porque los parámetros del constructor no son propiedades. Son solo parámetros. Si quieres que una propiedad tenga la visibilidad del setter modificada, debes declararla en el cuerpo de la clase.

\n\n

Cómo hacerlo correctamente:

\n\n
class User(name: String) {\n    var name: String = name\n        private set\n}
\n\n

O, si usas un data class, tendrás que ingeniártelas:

\n\n
data class User(private val _name: String) {\n    var name: String = _name\n        private set\n}
\n\n

Sí, un data class no permite cambiar la visibilidad del setter directamente para las propiedades del constructor primario. Tendrás que usar un backing field.

\n\n

Error n.º 2: Confusión con el backing field

\n\n

El backing field es un campo oculto que Kotlin genera automáticamente para una propiedad si usas field en el getter o setter. Pero si sobrescribes el getter o setter sin hacer referencia a field, el backing field no se crea.

\n\n

Ejemplo del problema:

\n\n
var counter: Int = 0\n    private set\n    get() = field * 2 // ❌ Error: field no está definido
\n\n

No, esto no es un error de compilación. Pero si escribes:

\n\n
var counter: Int = 0\n    private set\n    get() = 42 // todo bien, pero field no se usa
\n\n

En este caso, el backing field no se creará. Y si intentas acceder a field en el setter, obtendrás un error. La buena noticia: si usas private set, el backing field casi siempre se crea automáticamente, porque el setter por defecto usa field. Pero si sobrescribes el setter sin field, prepárate para sorpresas.

\n\n

Consejo: usa siempre explícitamente field en el getter y setter si quieres trabajar con el backing field. Y recuerda: si una propiedad no tiene backing fie

Blogs

Book Recommendations