DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Kotlin data class Patterns — copy, destructuring & equals

Master Kotlin data class features for efficient, readable code.

copy() for Immutable Updates

Create modified copies without mutation:

data class User(val id: Int, val name: String, val email: String)

val user = User(1, "Alice", "alice@example.com")
val updatedUser = user.copy(email = "newemail@example.com")
// Original user unchanged
Enter fullscreen mode Exit fullscreen mode

This pattern is essential for immutable state management.

Destructuring Declarations

Unpack data class values cleanly:

data class Point(val x: Int, val y: Int)

val (x, y) = Point(10, 20)
println("$x, $y")

// In for loops
val points = listOf(Point(1, 2), Point(3, 4))
for ((x, y) in points) {
    println("$x, $y")
}
Enter fullscreen mode Exit fullscreen mode

ViewModel UiState Pattern

Combine data classes with sealed classes for state:

sealed class UiState {
    object Loading : UiState()
    data class Success(val user: User) : UiState()
    data class Error(val message: String) : UiState()
}

// Use when for type-safe handling
when (val state = uiState.value) {
    is UiState.Loading -> LoadingScreen()
    is UiState.Success -> UserScreen(state.user)
    is UiState.Error -> ErrorScreen(state.message)
}
Enter fullscreen mode Exit fullscreen mode

Custom equals with Scope

Override equals for specific field comparison:

data class User(val id: Int, val name: String, val lastUpdated: Long) {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is User) return false
        // Only compare id and name, ignore lastUpdated
        return id == other.id && name == other.name
    }

    override fun hashCode(): Int = id.hashCode() + name.hashCode()
}
Enter fullscreen mode Exit fullscreen mode

Sealed Class Combination

Combine sealed classes and data classes for type safety:

sealed class Result<T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error<T>(val exception: Exception) : Result<T>()
    class Loading<T> : Result<T>()
}

// Pattern matching with destructuring
when (val result = apiCall()) {
    is Result.Success -> println(result.data)
    is Result.Error -> println(result.exception.message)
    is Result.Loading -> println("Loading...")
}
Enter fullscreen mode Exit fullscreen mode

Leverage data classes to write safer, more concise Kotlin code.


8 production-ready Android app templates on Gumroad.

Browse templatesGumroad

Top comments (0)