Question
In Kotlin, how do you correctly declare a var so that its getter is public, but its setter is private and can only be modified from inside the class?
For example, the goal is to allow other code to read the property, while preventing external code from assigning a new value to it.
Short Answer
By the end of this page, you will understand how Kotlin property accessors work, how to make a var publicly readable but privately writable, and when this pattern is useful in real applications. You will also see the exact syntax, step-by-step behavior, common mistakes, and a small practical project.
Concept
In Kotlin, a property like var name = "Alice" usually creates:
- a getter to read the value
- a setter to change the value
By default, both accessors have the same visibility as the property itself.
A common design need is this:
- other classes should be able to read the property
- only the owning class should be able to change it
Kotlin supports this directly by letting you change the visibility of the setter.
var count: Int = 0
private set
This means:
countcan be read from anywhere the property itself is visiblecountcan only be assigned from inside the class where it is declared
This matters because it helps you protect object state. Instead of letting any code change important values freely, you control updates through methods or internal logic. This is a core part of encapsulation.
For example, a class might expose a score, status, or balance that others can inspect, but only the class itself should decide how those values change.
In short:
- use
valwhen a property should never change after initialization - use
varwithprivate setwhen it should change, but only internally
Mental Model
Think of a property as a room with two doors:
- the getter door lets people look inside
- the setter door lets people go in and rearrange things
A normal var leaves both doors open.
A var with private set works like this:
- anyone allowed into the building can look through the getter door
- only the room owner has the key to the setter door
So other parts of the program can see the current state, but they cannot directly change it.
That gives the class control over its own data.
Syntax and Examples
Basic syntax
class User {
var name: String = "Guest"
private set
}
Here:
nameis a mutable property- the getter is public by default
- the setter is private
External code can do this:
val user = User()
println(user.name)
But this will fail:
user.name = "Sam" // Error: setter is private
Internal modification example
class Counter {
var count: Int = 0
private set
fun increment() {
count++
}
fun reset() {
count = 0
}
}
Step by Step Execution
Consider this code:
class BankAccount {
var balance: Int = 0
private set
fun deposit(amount: Int) {
if (amount > 0) {
balance += amount
}
}
}
fun main() {
val account = BankAccount()
println(account.balance)
account.deposit(50)
println(account.balance)
}
Step by step:
- A
BankAccountobject is created. balancestarts at0.println(account.balance)calls the public getter and prints0.account.deposit(50)calls a class method.- Inside
deposit, the class is allowed to use the private setter because it is inside the same class. balance += amountchangesbalancefrom to .
Real World Use Cases
This pattern appears often in real Kotlin programs.
1. Counters and metrics
class DownloadTracker {
var completedDownloads = 0
private set
fun markCompleted() {
completedDownloads++
}
}
Other code can read the count, but only the class can update it correctly.
2. State objects
class Connection {
var isConnected = false
private set
fun connect() {
isConnected = true
}
fun disconnect() {
isConnected = false
}
}
This prevents random code from setting connection state incorrectly.
3. Validation-based updates
class Temperature {
var celsius: =
{
(value >= -) {
celsius = value
}
}
}
Real Codebase Usage
In real codebases, private set is often used as part of defensive design.
Common patterns
Encapsulation
Expose state for reading, but force changes through methods.
class Order {
var status: String = "PENDING"
private set
fun ship() {
status = "SHIPPED"
}
}
This avoids invalid assignments like setting status to arbitrary strings from outside.
Guard clauses before updating
class ScoreBoard {
var score = 0
private set
fun addPoints(points: Int) {
if (points <= 0) return
score += points
}
}
The class validates data before changing state.
Error prevention
Common Mistakes
1. Using val when internal mutation is needed
Broken idea:
class Counter {
val count = 0
fun increment() {
// count++ // Error: val cannot be reassigned
}
}
Use var with private set if the class needs to update the property.
class Counter {
var count = 0
private set
fun increment() {
count++
}
}
2. Assuming private set makes the whole property private
class Example {
var value = 10
private set
}
This does make fully private. It only makes assignment private. Reading is still public if the property is public.
Comparisons
| Concept | Can read from outside? | Can write from outside? | Can write inside class? | Best use |
|---|---|---|---|---|
val x = ... | Yes | No | No | Truly read-only property |
var x = ... | Yes | Yes | Yes | Fully mutable property |
var x = ... private set | Yes | No | Yes | Publicly readable, internally controlled state |
private var x = ... | No | No | Yes | Fully hidden internal property |
Cheat Sheet
Quick syntax
class Example {
var value: Int = 0
private set
}
What it means
- getter: public by default
- setter: private
- outside code can read
- outside code cannot assign
- class methods can still assign
Example
class Counter {
var count = 0
private set
fun increment() {
count++
}
}
Rules
private setmust be placed under the property declaration- it only changes setter visibility
- the property must be a
var, not aval valhas no setter, soprivate setdoes not apply
Good use cases
FAQ
How do I make a Kotlin property readable publicly but writable only inside the class?
Use a var and place private set under it.
var count = 0
private set
Can I use private set with val in Kotlin?
No. A val does not have a setter, so there is nothing to make private.
Is the getter still public when I use private set?
Yes, if the property itself is public. Only the setter becomes private.
Can methods inside the same class change a property with private set?
Yes. The class that owns the property can still update it normally.
What is the difference between private var and var private set in Kotlin?
private var hides the property completely from outside code. var private set allows reading but blocks outside writing.
Why use instead of a normal public ?
Mini Project
Description
Build a simple Player class for a game. Other parts of the program should be able to read the player's level, but only the class itself should be allowed to change it. This demonstrates how to protect state while still exposing useful information.
Goal
Create a class with a publicly readable level property and a privately writable setter, then update the level through class methods.
Requirements
- Create a
Playerclass with alevelproperty. - Make the
levelproperty publicly readable but privately writable. - Add a method to increase the level.
- Add a method that prints player information.
- Show in
mainthat reading works and direct assignment does not.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Android AlarmManager Example: Scheduling Tasks with AlarmManager
Learn how to use Android AlarmManager to schedule tasks, set alarms, and handle broadcasts with a simple beginner example.
Android Foreground Service Notification Channels in Kotlin
Learn why startForeground fails on Android 8.1 and how to create a valid notification channel for foreground services in Kotlin.