Sobes.tech
Middle

Jaký je rozdíl mezi sealed třídami a abstraktními třídami v Kotlinu?

sobes.tech AI

Odpověď od AI

Hlavní rozdíl mezi sealed třídami a abstraktními třídami spočívá v tom, že sealed třídy omezují dědičnou hierarchii na úroveň jednoho souboru nebo modulu (pro Kotlin 1.5+). Dědici sealed třídy musí být deklarováni ve stejném souboru jako samotná sealed třída, což zajišťuje úplnou kontrolu při použití výrazů when.

Rozdíly:

  • Dědičnost:
    • Abstraktní třídy mohou být děděny kdekoliv v projektu.
    • Sealed třídy mohou být děděny pouze uvnitř stejného souboru (do Kotlin 1.5) nebo v rámci stejného modulu (s Kotlin 1.5+).
  • Použití s when:
    • Při použití when s sealed typem může kompilátor zkontrolovat, že všechny možné podtypy byly zahrnuty, což činí when úplným a odstraňuje potřebu explicitně uvádět větev else, pokud jsou všechny podtypy zpracovány.
    • S abstraktními třídami kompilátor nemůže garantovat úplnost, proto je často potřeba else.
  • Vytváření instancí:
    • Ani abstraktní, ani sealed třídy nelze přímo instancovat.
  • Členové:
    • Stejně jako abstraktní, tak i sealed třídy mohou mít abstraktní i neabstraktní členy.

Příklad sealed třídy:

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 -> {
            // Zpracování úspěšného výsledku
            println("Success: ${result.data}")
        }
        is Result.Error -> {
            // Zpracování chyby
            println("Error: ${result.message}")
        }
        // Není potřeba else, pokud jsou všechny dědici zpracováni
    }
}

Příklad abstraktní třídy:

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()
}

Kdy používat:

  • Sealed třídy: Ideální pro reprezentaci omezeného souboru možných stavů nebo typů, když potřebujete úplnou kontrolu v when výrazech. Často se používají pro modelování výsledků operací (úspěch/chyba), stavů UI, událostí.
  • Abstraktní třídy: Vhodné pro definování společné funkčnosti a kontraktu pro skupinu souvisejících tříd, které mohou být děděny kdekoliv v projektu.

Celkově sealed třídy poskytují přísnější kontrolu nad dědičnou hierarchií a zlepšují bezpečnost a čitelnost kódu při zpracování omezeného počtu podtypů.