Sobes.tech
Middle

Mis vahe on sealed klasside ja abstraktklasside vahel Kotlinis?

sobes.tech AI

Vastus AI-lt

The main difference between sealed classes and abstract classes is that sealed classes restrict the inheritance hierarchy within a single file or module (for Kotlin 1.5+). The subclasses of a sealed class must be declared in the same file as the sealed class itself, which ensures exhaustive checking in when expressions.

Differences:

  • Inheritance:
    • Abstract classes can be inherited anywhere in the project.
    • Sealed classes can only be inherited within the same file (up to Kotlin 1.5) or within the same module (with Kotlin 1.5+).
  • Using with when:
    • When used with a sealed type, the compiler can verify that all possible subtypes are considered, making when exhaustive and eliminating the need to explicitly specify an else branch if all subtypes are handled.
    • With abstract classes, the compiler cannot guarantee exhaustiveness, so an else branch is often required.
  • Creating instances:
    • Neither abstract nor sealed classes can be instantiated directly.
  • Members:
    • Both abstract and sealed classes can have abstract and non-abstract members.

Example of a sealed class:

sealed class Result<out T> {
    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val message: String) : Result<Nothing>()
}

fun processResult(result: Result<Int>) {
    when (result) {
        is Result.Success -> {
            // Handling successful result
            println("Success: ${result.data}")
        }
        is Result.Error -> {
            // Handling error
            println("Error: ${result.message}")
        }
        // No need for else if all subclasses are handled
    }
}

Example of an abstract class:

abstract class Shape {
    abstract fun area(): Double
}

class Circle(val radius: Double) : Shape() {
    override fun area(): Double = Math.PI * radius * radius
}

class Rectangle(val width: Double, val height: Double) : Shape() {
    override fun area(): Double = width * height
}

fun calculateArea(shape: Shape): Double {
    return shape.area()
}

When to use:

  • Sealed classes: Ideal for representing a limited set of states or types where exhaustive checking in when expressions is needed. Often used for modeling operation results (success/error), UI states, events.
  • Abstract classes: Suitable for defining common functionality and contracts for a group of related classes that can be inherited anywhere in the project.

In summary, sealed classes provide stricter control over inheritance hierarchy and improve safety and readability of code when handling a limited set of subtypes.