3 Practical Examples of Kotlin Sealed Classes

Explore three diverse examples of Kotlin sealed classes to understand their practical applications in programming.
By Jamie

Understanding Kotlin Sealed Classes

Kotlin sealed classes are a powerful feature that allows you to define a restricted class hierarchy. Unlike regular classes, sealed classes can only be subclassed within the same file. This makes them particularly useful for representing a fixed set of types, which can be helpful in scenarios like state management or handling various data responses. Below are three practical examples of Kotlin sealed classes to illustrate their usage in real-world applications.

Example 1: Network Response Handling

Context

When dealing with network operations, it’s common to have multiple states for the response, such as success, error, or loading. Using sealed classes allows for a clearer representation of these states.

sealed class NetworkResponse<out T> {
    data class Success<out T>(val data: T) : NetworkResponse<T>()
    data class Error(val exception: Exception) : NetworkResponse<Nothing>()
    object Loading : NetworkResponse<Nothing>()
}

fun handleResponse(response: NetworkResponse<String>) {
    when (response) {
        is NetworkResponse.Success -> println("Data received: \
${response.data}")
        is NetworkResponse.Error -> println("Error occurred: \
${response.exception.message}")
        NetworkResponse.Loading -> println("Loading...")
    }
}

Notes

Using sealed classes helps ensure that all possible states are handled in the when expression, preventing any unhandled cases that could lead to runtime errors.

Example 2: Representing UI States

Context

In a typical Android application, the UI can be in multiple states such as idle, loading, or displaying data. Sealed classes can effectively model these UI states.

sealed class UiState {
    object Idle : UiState()
    object Loading : UiState()
    data class Success(val data: List<String>) : UiState()
    data class Error(val message: String) : UiState()
}

fun updateUiState(state: UiState) {
    when (state) {
        is UiState.Idle -> showIdleView()
        is UiState.Loading -> showLoadingView()
        is UiState.Success -> showData(state.data)
        is UiState.Error -> showError(state.message)
    }
}

Notes

Using sealed classes for UI states makes the codebase cleaner and easier to maintain, as it gives a clear structure to the different states the UI can be in.

Example 3: User Authentication States

Context

In applications that require user authentication, there are various states such as logged in, logged out, or error. Sealed classes can encapsulate these states clearly.

sealed class AuthState {
    object LoggedIn : AuthState()
    object LoggedOut : AuthState()
    data class Error(val message: String) : AuthState()
}

fun handleAuthState(state: AuthState) {
    when (state) {
        AuthState.LoggedIn -> navigateToHome()
        AuthState.LoggedOut -> navigateToLogin()
        is AuthState.Error -> showError(state.message)
    }
}

Notes

This approach centralizes the handling of authentication states, making it easier to expand or modify in the future without affecting other parts of the application.