Visibility Modifiers
Prerequisites: Classes and objects
Visibility modifiers control which code can see a class, property, or function. Hiding implementation details lets you change them later without breaking other code — this is encapsulation.
The four levels
| Modifier | Visible to |
|---|---|
public |
Everyone — the default |
internal |
Anything in the same module (one Gradle module, for example) |
protected |
The class and its subclasses |
private |
Inside the class only (or, at the top level, inside the file) |
Example
class PasswordValidator(private val minimumLength: Int = 8) {
fun isStrong(password: String) = isLongEnough(password) && hasDigit(password)
private fun isLongEnough(password: String) = password.length >= minimumLength
private fun hasDigit(password: String) = password.any { it.isDigit() }
}
fun main() {
val validator = PasswordValidator()
println(validator.isStrong("abc12345"))
println(validator.isStrong("password"))
}
true
false
isStrong is the class's interface. The private helpers can be renamed
or rewritten freely — nothing outside can call them. Trying
validator.hasDigit("x") fails to compile:
Cannot access 'fun hasDigit(password: String): Boolean': it is private in 'PasswordValidator'.
Constructor properties can be private too — private val minimumLength
is stored in the object but hidden from outside.
Read-only from outside
A common pattern exposes a read-only view of mutable internal state:
class Playlist {
private val _songs = mutableListOf<String>()
val songs: List<String> get() = _songs
fun add(song: String) {
_songs += song
}
}
fun main() {
val p = Playlist()
p.add("Intro")
println(p.songs)
}
[Intro]
Outside code sees a read-only List and can't add songs directly.
In apps and libraries
In an app, public (the default) and private cover most needs. In a
library, mark helpers internal or private, since everything
public is part of what you promise to keep working.