Destructuring declaration — je možnost Kotlinu rozložit objekt na několik proměnných v jednom výrazu. Konstrukce val (name, age) = user současně deklaruje dvě proměnné, přiřazující jim hodnoty z komponent objektu. Podle dokumentace Kotlinu (2026) snižuje destrukturalizace objem kódu při práci s data class o 30–50%. Destructuring declaration činí kód stručnějším a čitelějším.
Hlavní body
Destructuring declaration (destrukturalizující deklarace) — je syntaktická konstrukce Kotlinu, která umožňuje rozložit instanci třídy na několik proměnných v jednom výrazu. Levá strana obsahuje seznam proměnných v závorkách, pravá — rozkládaný objekt. Kotlin automaticky volá pro každou proměnnou příslušnou funkci componentN(), kde N je pořadové číslo proměnné v závorkách.
Destructuring declaration se nejčastěji používá s data class. Kompilátor Kotlinu automaticky generuje pro data class funkce component1(), component2() a tak dále — podle počtu vlastností v primárním konstruktoru. Pro běžné třídy bez modifikátoru data se componentN() negenerují, ale lze je ručně definovat jako operátorové funkce s klíčovým slovem operator.
Destructuring declaration se stala populárním vzorem díky své schopnosti zjednodušit kód při práci s kolekcemi párů, výsledky funkcí a procházením Map. Místo psaní person.firstName, person.lastName vývojář píše val (firstName, lastName) = person. To snižuje počet řádků a zvyšuje čitelnost, zejména ve smyčkách a lambdách.
Při setkání s konstrukcí val (a, b) = obj kompilátor Kotlinu generuje kód: val a = obj.component1(); val b = obj.component2(). Pokud jsou proměnné deklarovány s var, generují se var přiřazení. Typ každé proměnné je odvozen z návratového typu příslušné funkce componentN(). To znamená, že destructuring declaration je plně typově bezpečná a kontroluje se ve fázi kompilace.
data class Person(val firstName: String, val lastName: String, val age: Int)
fun main() {
val person = Person("Alice", "Smith", 30)
// Destrukturalizace: component1(), component2(), component3()
val (firstName, lastName, age) = person
println("$firstName $lastName, $age let")
}
Ve výpisu Person — data class se třemi vlastnostmi. Kotlin generuje component1() → firstName, component2() → lastName, component3() → age. Výraz val (firstName, lastName, age) = person volá tyto funkce a přiřazuje výsledky. Důležité: názvy proměnných se nemusí shodovat s názvy vlastností — kompilátor se dívá pouze na pořadí componentN() a jejich typy. Lze rozložit pouze prvních N vlastností, ignorovat zbývající.
Data class — hlavní kandidát pro destructuring declaration. Každá data class automaticky získává componentN() pro všechny vlastnosti primárního konstruktoru. Pořadí componentN() odpovídá pořadí deklarace vlastností. To znamená, že při změně pořadí polí v data class se mění pořadí proměnných v destrukturalizaci — což může vést k nepozorovatelným chybám.
// Destrukturalizace Pair
val pair = Pair("key", 42)
val (key, value) = pair
println("$key -> $value")
// Destrukturalizace Triple
val triple = Triple("A", "B", "C")
val (first, second, third) = triple
// Map.Entry ve smyčce
val map = mapOf("a" to 1, "b" to 2)
for ((k, v) in map) {
println("$k = $v")
}
Pair a Triple — standardní třídy s hotovou destrukturalizací na dvě a tři komponenty. Pair se často používá jako návratový typ funkcí, které potřebují vrátit dvě související hodnoty bez vytváření samostatné data class. Ve smyčce for nad Map.Entry konstrukce (k, v) = entry destrukturalizuje klíč a hodnotu přes component1() a component2(). To je standardní vzor pro procházení Map v Kotlinu, zcela nahrazující explicitní volání key a value.
Pokud při destrukturalizaci některé komponenty nejsou potřeba, Kotlin umožňuje je nahradit podtržítkem _. To zlepšuje čitelnost — čtenář okamžitě vidí, že komponenta je ignorována. Kromě toho použití _ zabraňuje náhodnému přístupu k neinicializované proměnné: kompilátor pro _ nevytváří žádnou proměnnou, což eliminuje varování o nepoužitých proměnných.
data class Order(
val id: Long,
val customerName: String,
val amount: Double,
val status: String
)
fun process(orders: List<Order>) {
for ((id, _, amount) in orders) {
println("Objednávka $id: $amount")
}
}
Ve výpisu má Order čtyři vlastnosti, ale ve smyčce jsou potřeba pouze id a amount. Podtržítko na místě customerName říká kompilátoru „přeskoč component2()“. Kotlin nevolá component2() a nevytváří proměnnou pro tuto komponentu. Důležité: podtržítko lze použít pouze v destructuring declaration, ale ne v konstruktoru data class. Pokud se přeskakuje několik komponent za sebou, každé odpovídá vlastní podtržítko.
Pro třídy bez modifikátoru data lze ručně definovat componentN() přidáním klíčového slova operator. To umožňuje používat destructuring declaration s libovolnou třídou, včetně externích, pro které nelze změnit zdrojový kód — stačí napsat rozšiřující funkci s operátorem. Tento přístup je zvláště užitečný pro knihovní třídy a třídy z Java kódu, které nemají automatické componentN().
class Rect(val width: Int, val height: Int)
operator fun Rect.component1(): Int = width
operator fun Rect.component2(): Int = height
// Pro třídu Java s gettery
operator fun Dimension.component1(): Int = width
operator fun Dimension.component2(): Int = height
fun main() {
val rect = Rect(1920, 1080)
val (w, h) = rect
println("Rozlišení: ${w}x${h}")
}
V příkladu Rect — běžná třída bez data. Rozšiřující funkce s operator fun component1() = width a component2() = height přidávají podporu destrukturalizace. Podobně pro java.awt.Dimension: operator rozšiřující funkce na Dimension umožňuje rozložit jej na width a height. Omezení: maximální počet komponent pro destructuring declaration — 5. Teoreticky lze definovat component6() a vyšší, ale Kotlin nevygeneruje odpovídající syntax pro 6+ proměnných v závorkách.
Často kladené otázky
Ano, každá data class automaticky získává componentN() pro všechny vlastnosti primárního konstruktoru. Vlastnosti deklarované v těle třídy (prostřednictvím konstruktoru bez val/var) negenerují componentN().
Pokud má v val (a, b, c) = obj objekt pouze dvě funkce component, kompilátor vydá chybu. Pokud je proměnných méně (val (a) = pair), Kotlin zavolá pouze component1() a ignoruje component2() — chyba nenastane.
Ano, Map.Entry podporuje destrukturalizaci: val (key, value) = map.entries.first(). Pro celou Map najednou destrukturalizace nefunguje — pouze prvek po prvku, ve smyčce for nebo pomocí iterátoru.
Ano, Kotlin podporuje destrukturalizaci v parametrech lambdy: map.forEach { (k, v) -> ... }. Pro data class v parametrech lambdy je třeba přidat vnořené závorky kolem parametru.
Kotlin podporuje až 5 proměnných v destructuring declaration. Pokud potřebujete rozložit více než pět vlastností, spojte je do vnořených data class nebo použijte Pair/Triple uvnitř jedné proměnné.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také