Encapsulation with Backing Properties

Read-only Outside, Mutable Inside

A common Kotlin pattern: keep a private mutable property (named with an underscore) and expose a public read-only view of it. Callers cannot add or remove items; only the class's functions can.

Example

class TodoList {
    private val _items = mutableListOf<String>()
    val items: List<String> get() = _items     // read-only view

    fun add(task: String) {
        require(task.isNotBlank()) { "Task cannot be blank" }
        _items.add(task.trim())
    }
}

fun main() {
    val todo = TodoList()
    todo.add("Learn sealed classes")
    todo.add("  Build a Compose screen ")
    println(todo.items)
    // todo.items.add("x")   -> error: List has no add()
}

Output

[Learn sealed classes, Build a Compose screen]

Exercise

Exercise: Write a Wallet class whose balance can be read by anyone but changed only by addMoney() and spend(); spend() returns false when the balance is too low.

Show answer
class Wallet {
    var balance = 0.0
        private set

    fun addMoney(amount: Double) { if (amount > 0) balance += amount }
    fun spend(amount: Double): Boolean {
        if (amount > balance) return false
        balance -= amount
        return true
    }
}