What does `private set` do on a property, and how is it different from making the whole property private or using a val?
answer
- Public read, private write
- Only the setter visibility changes; getter stays public
- val = immutable for all; private set = class can still mutate
- private var hides reads too
- Setter must be <= property visibility
basics
~10 sprivate set lets anyone read the property but only code inside the class change it. The outside world sees a read-only value; the class can still update it internally.
solid answer
~40 s`var count: Int = 0; private set` gives the getter the property's default (public) visibility but restricts the **setter** to private. Outside the class the property is effectively read-only; inside, the class freely reassigns it. This differs from `val`, which is immutable for everyone including the class. It differs from making the whole property private, which would also hide the getter. The pattern enforces encapsulation: expose observable state, control mutation. You can set any narrower visibility on the setter (`protected set`, `internal set`). You only annotate the setter's visibility; without a body it stays auto-generated. It's the idiomatic way to model 'externally read-only, internally mutable' state.
code
kotlin · 6 linesclass Session {
var token: String? = null
private set
fun login(t: String) { token = t } // only the class mutates
fun logout() { token = null }
}go deeper
Knows private set means readable outside, writable only inside the class.
Contrasts it precisely with val and private var and knows other setter visibilities (internal/protected).
Connects it to encapsulation/invariants and the MutableStateFlow-as-StateFlow exposure pattern.
Treats it as API surface design: minimizing the mutation surface, ensuring all writes funnel through validated methods for thread-safety and auditing.
## The construct ```kotlin class Counter { var value: Int = 0 private set // getter public, setter private fun increment() { value++ } // allowed: inside the class } val c = Counter() val v = c.value // OK: read is public // c.value = 5 // COMPILE ERROR: setter is private c.increment() // OK: mutation goes through class API ``` ## What it means A `var` has two accessors: a getter and a setter. You can give the **setter** a more restrictive visibility than the property/getter. `private set` keeps the getter at the property's declared visibility (public by default) but makes the setter `private`. Result: **publicly readable, privately writable**. You only write the visibility modifier; you do **not** need a body. The setter is still auto-generated. ## Allowed setter visibilities - `private set` — only this class. - `protected set` — this class and subclasses. - `internal set` — same Gradle/Maven module. The setter visibility must be **equal to or more restrictive** than the getter/property visibility — you cannot make a setter *more* visible than the property. ## How it differs from alternatives | Construct | Readable by outside | Writable by outside | Writable by class | |---|---|---|---| | `var` (default) | yes | yes | yes | | `var ... private set` | yes | no | yes | | `val` | yes | no | **no** (immutable) | | `private var` | no | no | yes | Key distinction: `val` is immutable for everyone; `private set` keeps the value mutable for the class but read-only outside. `private var` also hides reads. ## Why it matters This is the standard encapsulation idiom for mutable observable state — e.g. a `loading` flag, a cached `_state`, or exposing read-only state in Android/Compose ViewModels (often paired with a backing `MutableStateFlow` exposed as `StateFlow`). It lets you guarantee all mutation passes through your methods so you can validate, log, or notify.
- Can you make the setter MORE visible than the getter, e.g. public setter on an internal property?No. The setter's visibility must be the same as or more restrictive than the property/getter. You can only narrow it.
- How does this relate to exposing StateFlow in a ViewModel?Same intent at the type level: a private MutableStateFlow is exposed as a read-only StateFlow. `private set` achieves the read-only-outside guarantee for plain properties.
Like a museum exhibit behind glass: visitors can look (read) but only staff inside can rearrange it (write).
saying these in an interview costs you the question
- Saying private set makes the property immutable like val
- Claiming you can make the setter more public than the getter
- Confusing private set with private var (which hides reads)
- Thinking you must write a setter body to use private set
- Believing private set blocks mutation from inside the class