Real World Example

Android ViewModel State

Every modern Android app uses this pattern: the ViewModel owns a private MutableStateFlow and exposes a public read-only StateFlow. The UI can observe the state but cannot change it directly.

class CartViewModel(private val repo: CartRepository) : ViewModel() {

    private val _uiState = MutableStateFlow(CartUiState())
    val uiState: StateFlow<CartUiState> = _uiState.asStateFlow()

    fun addItem(product: Product) {
        _uiState.update { it.copy(items = it.items + product) }
    }

    private fun recalculateTotal() { /* hidden helper */ }
}

A Bank Account That Cannot Be Broken

Example

Net-banking apps never let outside code set a balance. All changes go through validated functions and are recorded.

class BankAccount(val accountNo: String) {
    var balance = 0L
        private set
    private val _history = mutableListOf<String>()
    val history: List<String> get() = _history

    fun deposit(amount: Long) {
        require(amount > 0) { "Deposit must be positive" }
        balance += amount
        record("CREDIT", amount)
    }

    fun withdraw(amount: Long): Boolean {
        if (amount > balance) { record("DECLINED", amount); return false }
        balance -= amount
        record("DEBIT", amount)
        return true
    }

    private fun record(type: String, amount: Long) = _history.add("$type $amount -> $balance")
}

fun main() {
    val acc = BankAccount("SBI-001")
    acc.deposit(5000)
    acc.withdraw(1200)
    acc.withdraw(9000)
    acc.history.forEach(::println)
    println("Final balance: ${acc.balance}")
}

Output

CREDIT 5000 -> 5000
DEBIT 1200 -> 3800
DECLINED 9000 -> 3800
Final balance: 3800