Destructuring declaration — Kotlin-in bir ifadədə obyekti bir neçə dəyişənə parçalamaq imkanıdır. val (name, age) = user konstruksiyası eyni anda iki dəyişən elan edir, onlara obyektin komponentlərindən dəyərlər təyin edir. Kotlin sənədlərinə (2026) görə, destrukturizasiya data class ilə işləyərkən kod həcmini 30–50% azaldır. Destructuring declaration kodu daha yığcam və oxunaqlı edir.
Əsas məqamlar
Destructuring declaration (parçalayan deklarasiya) — Kotlin-in sinif nümunəsini bir ifadədə bir neçə dəyişənə parçalamağa imkan verən sintaktik konstruksiyadır. Sol tərəfdə mötərizələrdə dəyişənlərin siyahısı, sağ tərəfdə parçalanan obyekt yerləşir. Kotlin hər dəyişən üçün müvafiq componentN() funksiyasını avtomatik çağırır, burada N mötərizələrdə dəyişənin sıra nömrəsidir.
Destructuring declaration ən çox data class ilə istifadə olunur. Kotlin kompilyatoru data class üçün avtomatik olaraq component1(), component2() və s. funksiyaları yaradır — birinci konstruktordakı xassələrin sayına görə. Data modifikatoru olmayan adi siniflər üçün componentN() yaradılmır, lakin onları operator açar sözü ilə əl ilə təyin etmək olar.
Destructuring declaration cütlük kolleksiyaları, funksiya nəticələri və Map-i dövr etmə ilə işləyərkən kodu sadələşdirmək qabiliyyətinə görə məşhur nümunəyə çevrilmişdir. person.firstName, person.lastName yazmaq əvəzinə proqramçı val (firstName, lastName) = person yazır. Bu, sətirlərin sayını azaldır və oxunaqlılığı artırır, xüsusən döngələrdə və lambdalarda.
val (a, b) = obj konstruksiyası ilə qarşılaşdıqda Kotlin kompilyatoru aşağıdakı kodu yaradır: val a = obj.component1(); val b = obj.component2(). Əgər dəyişənlər var ilə elan edilibsə, var təyinatları yaradılır. Hər dəyişənin növü müvafiq componentN() funksiyasının qaytardığı növdən çıxarılır. Bu o deməkdir ki, destructuring declaration tamamilə tip-təhlükəsizdir və kompilyasiya mərhələsində yoxlanılır.
data class Person(val firstName: String, val lastName: String, val age: Int)
fun main() {
val person = Person("Alice", "Smith", 30)
// Destrukturizasiya: component1(), component2(), component3()
val (firstName, lastName, age) = person
println("$firstName $lastName, $age yaş")
}
Listinqdə Person — üç xassəli data class-dır. Kotlin component1() → firstName, component2() → lastName, component3() → age yaradır. val (firstName, lastName, age) = person ifadəsi bu funksiyaları çağırır və nəticələri təyin edir. Vacib: dəyişən adları xassə adları ilə üst-üstə düşməyə bilər — kompilyator yalnız componentN() sırasına və onların tiplərinə baxır. Qalanlarını nəzərə almayaraq yalnız ilk N xassəni parçalamaq olar.
Data class — destructuring declaration üçün əsas namizəddir. Hər bir data class birinci konstruktorun bütün xassələri üçün avtomatik olaraq componentN() alır. componentN() sırası xassələrin elan edilmə sırasına uyğundur. Bu o deməkdir ki, data class-da sahələrin sırası dəyişdirildikdə destrukturizasiyada dəyişənlərin sırası dəyişir — bu da hiss olunmayan səhvlərə səbəb ola bilər.
// Pair destrukturizasiyası
val pair = Pair("key", 42)
val (key, value) = pair
println("$key -> $value")
// Triple destrukturizasiyası
val triple = Triple("A", "B", "C")
val (first, second, third) = triple
// Döngüdə Map.Entry
val map = mapOf("a" to 1, "b" to 2)
for ((k, v) in map) {
println("$k = $v")
}
Pair və Triple — iki və üç komponent üçün hazır destrukturizasiya ilə standart siniflərdir. Pair tez-tez ayrıca data class yaratmadan iki əlaqəli dəyər qaytarmalı olan funksiyaların qaytarma növü kimi istifadə olunur. Map.Entry üzərində for döngəsində (k, v) = entry konstruksiyası component1() və component2() vasitəsilə açarı və dəyəri destrukturizasiya edir. Bu, Kotlin-də Map-i dövr etmək üçün standart nümunədir və key və value-nin açıq çağırışlarını tamamilə əvəz edir.
Destrukturizasiya zamanı bəzi komponentlər lazım deyilsə, Kotlin onları alt xətt _ ilə əvəz etməyə imkan verir. Bu, oxunaqlılığı yaxşılaşdırır — oxucu dərhal görür ki, komponent nəzərə alınmır. Bundan əlavə, _ istifadəsi təsadüfən başladılmamış dəyişənə müraciətin qarşısını alır: kompilyator _ üçün heç bir dəyişən yaratmır, bu da istifadə olunmayan dəyişənlər haqqında xəbərdarlıqları aradan qaldırır.
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("Sifariş $id: $amount")
}
}
Listinqdə Order dörd xassəyə malikdir, lakin döngədə yalnız id və amount lazımdır. customerName yerində alt xətt kompilyatora «component2()-ni atla» deyir. Kotlin component2()-ni çağırmır və bu komponent üçün dəyişən yaratmır. Vacib: alt xətt yalnız destructuring declaration-da istifadə edilə bilər, lakin data class konstruktorunda yox. Ardıcıl bir neçə komponent buraxılırsa, hər birinə öz alt xətti uyğun gəlir.
Data modifikatoru olmayan siniflər üçün operator açar sözünü əlavə edərək componentN() əl ilə təyin etmək olar. Bu, istənilən siniflə, o cümlədən mənbə kodu dəyişdirilə bilməyən üçüncü tərəf sinifləri ilə destructuring declaration istifadə etməyə imkan verir — operator ilə genişləndirmə funksiyası yazmaq kifayətdir. Bu yanaşma kitabxana sinifləri və avtomatik componentN() olmayan Java kodundan siniflər üçün xüsusilə faydalıdır.
class Rect(val width: Int, val height: Int)
operator fun Rect.component1(): Int = width
operator fun Rect.component2(): Int = height
// Getter-ləri olan Java sinfi üçün
operator fun Dimension.component1(): Int = width
operator fun Dimension.component2(): Int = height
fun main() {
val rect = Rect(1920, 1080)
val (w, h) = rect
println("Qətnamə: ${w}x${h}")
}
Nümunədə Rect — data olmadan adi sinifdir. operator fun component1() = width və component2() = height ilə genişləndirmə funksiyaları destrukturizasiya dəstəyi əlavə edir. Eynilə java.awt.Dimension üçün: Dimension-da operator genişləndirməsi onu width və height-ə parçalamağa imkan verir. Məhdudiyyət: destructuring declaration üçün maksimum komponent sayı 5-dir. Nəzəri olaraq component6() və daha yüksəkləri təyin etmək olar, lakin Kotlin mötərizələrdə 6+ dəyişən üçün müvafiq sintaksis yaratmayacaq.
Tez-tez verilən suallar
Bəli, hər bir data class birinci konstruktorun bütün xassələri üçün avtomatik olaraq componentN() alır. Sinif gövdəsində elan edilən xassələr (val/var olmadan konstruktor vasitəsilə) componentN() yaratmır.
Əgər val (a, b, c) = obj-də obyektin yalnız iki component funksiyası varsa, kompilyator səhv verəcək. Dəyişənlər az olduqda (val (a) = pair), Kotlin yalnız component1()-i çağıracaq və component2()-ni nəzərə almayacaq — səhv olmayacaq.
Bəli, Map.Entry destrukturizasiyanı dəstəkləyir: val (key, value) = map.entries.first(). Bütün Map-i birdən destrukturizasiya etmək işləmir — yalnız element-element, for döngəsində və ya iterator vasitəsilə.
Bəli, Kotlin lambda parametrlərində destrukturizasiyanı dəstəkləyir: map.forEach { (k, v) -> ... }. Lambda parametrlərində data class üçün parametr ətrafında iç-içə mötərizələr əlavə etmək lazımdır.
Kotlin destructuring declaration-da 5 dəyişənə qədər dəstəkləyir. Beşdən çox xassə parçalamaq lazımdırsa, onları iç-içə data class-larda birləşdirin və ya bir dəyişən daxilində Pair/Triple istifadə edin.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun