Generics
class Box<T>(val value: T)
val intBox = Box(42)
val strBox = Box("hi")
fun <T> firstOrNull(list: List<T>): T? = if (list.isEmpty()) null else list[0]
Sealed classes (great for state)
sealed class Result {
data class Success(val data: String) : Result()
data class Error(val message: String) : Result()
object Loading : Result()
}
fun render(r: Result) = when (r) {
is Result.Success -> show(r.data)
is Result.Error -> showError(r.message)
Result.Loading -> showSpinner()
// no else needed: compiler knows all cases
}
Flow (streams of values)
fun ticker(): Flow<Int> = flow {
var i = 0
while (true) { emit(i++); delay(1000) }
}
lifecycleScope.launch {
ticker().collect { println(it) } // 0, 1, 2, ...
}
Use sealed classes to model UI state (Loading/Success/Error) — combined with Flow they make reactive, bug-resistant apps.