En Kotlin, los modificadores de visibilidad determinan desde dónde se puede acceder a las clases, objetos, interfaces, constructores, funciones y propiedades. Comprender estos modificadores es crucial para diseñar aplicaciones seguras y bien estructuradas.
Tipos de Modificadores de Visibilidad
Kotlin proporciona cuatro modificadores de visibilidad:
- public: El miembro es accesible desde cualquier lugar.
 - private: El miembro es accesible solo dentro del archivo o clase donde se declara.
 - protected: El miembro es accesible dentro de la clase y sus subclases.
 - internal: El miembro es accesible dentro del mismo módulo.
 
- public
 
El modificador public es el predeterminado. Si no se especifica ningún modificador de visibilidad, el miembro es public.
class PublicClass {
    public var publicProperty: String = "I am public"
    
    public fun publicFunction() {
        println("This is a public function")
    }
}
- private
 
El modificador private restringe el acceso al miembro solo dentro del archivo o clase donde se declara.
class PrivateClass {
    private var privateProperty: String = "I am private"
    
    private fun privateFunction() {
        println("This is a private function")
    }
    
    fun accessPrivateMembers() {
        println(privateProperty)
        privateFunction()
    }
}
- protected
 
El modificador protected permite el acceso dentro de la clase y sus subclases. No es aplicable a los miembros de nivel superior (top-level).
open class ProtectedClass {
    protected var protectedProperty: String = "I am protected"
    
    protected fun protectedFunction() {
        println("This is a protected function")
    }
}
class SubClass : ProtectedClass() {
    fun accessProtectedMembers() {
        println(protectedProperty)
        protectedFunction()
    }
}
- internal
 
El modificador internal hace que el miembro sea accesible solo dentro del mismo módulo. Un módulo es un conjunto de archivos Kotlin compilados juntos.
internal class InternalClass {
    internal var internalProperty: String = "I am internal"
    
    internal fun internalFunction() {
        println("This is an internal function")
    }
}Comparación de Modificadores de Visibilidad
| Modificador | Accesibilidad | 
|---|---|
| public | En cualquier lugar | 
| private | Dentro del archivo o clase | 
| protected | Dentro de la clase y subclases | 
| internal | Dentro del mismo módulo | 
Ejemplos Prácticos
Ejemplo 1: Uso de private en una Clase
class ExamplePrivate {
    private var secret: String = "This is a secret"
    
    fun revealSecret() {
        println(secret)
    }
}
fun main() {
    val example = ExamplePrivate()
    // example.secret // Error: Cannot access 'secret': it is private in 'ExamplePrivate'
    example.revealSecret() // Output: This is a secret
}Ejemplo 2: Uso de protected en Herencia
open class Parent {
    protected var familySecret: String = "Family secret"
}
class Child : Parent() {
    fun showFamilySecret() {
        println(familySecret)
    }
}
fun main() {
    val child = Child()
    child.showFamilySecret() // Output: Family secret
}Ejemplo 3: Uso de internal en un Módulo
internal class InternalExample {
    internal var internalData: String = "Internal data"
}
fun main() {
    val example = InternalExample()
    println(example.internalData) // Output: Internal data
}Ejercicio Práctico
Ejercicio 1: Modificadores de Visibilidad
- 
Crea una clase
BankAccountcon las siguientes propiedades y métodos:accountNumber(public)balance(private)deposit(amount: Double)(public)withdraw(amount: Double)(public)printBalance()(public)
 - 
Implementa la clase de manera que solo se pueda acceder al balance a través de los métodos
depositywithdraw. 
Solución
class BankAccount(val accountNumber: String) {
    private var balance: Double = 0.0
    
    fun deposit(amount: Double) {
        if (amount > 0) {
            balance += amount
            println("Deposited: $$amount")
        }
    }
    
    fun withdraw(amount: Double) {
        if (amount > 0 && amount <= balance) {
            balance -= amount
            println("Withdrew: $$amount")
        } else {
            println("Insufficient funds")
        }
    }
    
    fun printBalance() {
        println("Balance: $$balance")
    }
}
fun main() {
    val account = BankAccount("123456")
    account.deposit(100.0)
    account.withdraw(50.0)
    account.printBalance() // Output: Balance: $50.0
}Conclusión
Los modificadores de visibilidad en Kotlin son esenciales para controlar el acceso a los miembros de una clase y garantizar la encapsulación adecuada. Al comprender y utilizar estos modificadores correctamente, puedes diseñar aplicaciones más seguras y mantenibles. En el siguiente tema, exploraremos las clases de datos y las clases selladas, que son características avanzadas de Kotlin para modelar datos de manera más efectiva.
Curso de Programación en Kotlin
Módulo 1: Introducción a Kotlin
- Introducción a Kotlin
 - Configuración del Entorno de Desarrollo
 - Conceptos Básicos de Kotlin: Variables y Tipos de Datos
 - Flujo de Control: Condicionales y Bucles
 - Funciones y Lambdas
 
Módulo 2: Programación Orientada a Objetos en Kotlin
- Clases y Objetos
 - Herencia e Interfaces
 - Modificadores de Visibilidad
 - Clases de Datos y Clases Selladas
 - Declaraciones de Objetos y Objetos Compañeros
 
Módulo 3: Características Avanzadas de Kotlin
- Colecciones y Genéricos
 - Funciones de Extensión
 - Funciones de Orden Superior y Programación Funcional
 - Corrutinas y Programación Asíncrona
 - DSL (Lenguaje Específico de Dominio) en Kotlin
 
Módulo 4: Kotlin para Desarrollo Android
- Introducción al Desarrollo Android con Kotlin
 - Construcción de Interfaces de Usuario
 - Manejo de Entrada del Usuario
 - Redes y Almacenamiento de Datos
 - Pruebas y Depuración
 
