Encapsulation hides implementation details behind a restricted public interface, preserving control over which operations consumers can perform. section 16.3.1
Extending a class without breaking encapsulation
Kotlin extension functions can add behavior to existing JVM classes, including final classes, but they cannot access private or protected members. For example, `fun String.lastChar(): Char = get(length - 1)` adds a convenient operation while leaving String's hidden state protected; calling `"Kotlin".lastChar()` returns `n`. section 3.3
Expose read-only flow access
A class can keep `MutableSharedFlow<Int>` private and expose `messageFlow` as `SharedFlow<Int>`. Internal code emits through `_messageFlow`, while consumers can subscribe without gaining the ability to emit values. section 16.3.1
Listing 16.9 Broadcasting values using SharedFlow
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.random.*
import kotlin.time.Duration.Companion.milliseconds
class RadioStation {
private val _messageFlow = MutableSharedFlow<Int>() #1
val messageFlow = _messageFlow.asSharedFlow() #2
fun beginBroadcasting(scope: CoroutineScope) {
scope.launch {
while(true) {
delay(500.milliseconds)
val number = Random.nextInt(0..10)
log("Emitting $number!")
_messageFlow.emit(number) #3
}
}
}
}
The complete RadioStation listing demonstrates the private mutable flow, public read-only view, and controlled emission boundary. section 16.3.1













