Visibility & Packages
Packages and imports
Each file can declare a package; imports bring in names from elsewhere:
package com.example.banking
import kotlin.math.max
The package should usually mirror the directory structure, though Kotlin does not strictly require it.
Visibility modifiers
| Modifier | Visible to |
|---|---|
public (default) |
Everyone |
internal |
The same Gradle module |
protected |
The declaring class and subclasses |
private |
The declaring class (or file, for top-level declarations) |
class Vault {
private val secret = "🔑" // only inside Vault
internal val auditId = 42 // anywhere in this module
protected open val policy = "std" // subclasses can see it
fun reveal() = secret // public by default
}
For top-level declarations, private means “visible only within this
file”:
private fun helper() { /* file-private */ }
There is no package-private like Java. The closest equivalent is internal,
which is scoped to the whole module rather than a single package.
Why restrict visibility?
Keeping fields private and exposing behavior through public methods is
encapsulation — it lets you change internals without breaking callers and
keeps invariants (like a non-negative balance) enforced in one place.
Exercises
-
Take the
BankAccountfrom the previous chapter and make itsbalancesetterprivateso callers must usedeposit/withdraw. (It already is — confirm whyaccount.balance = -100does not compile.) -
Add an
internalfunctionauditLine(): Stringthat returns a one-line summary, usable from elsewhere in the module but not from outside it.
Previous: Classes & Properties · Next: Inheritance & Interfaces