Destructuring declaration — چیست، نحو و کاربرد در Kotlin

نویسنده: IT Sectr منتشر شده: 2026-06-23 زمان مطالعه: 7 دقیقه

Destructuring declaration — قابلیتی در Kotlin است که یک شی را به چند متغیر در یک عبارت تجزیه می‌کند. ساختار val (name, age) = user همزمان دو متغیر را اعلام می‌کند و مقادیر را از اجزای شی به آن‌ها اختصاص می‌دهد. طبق مستندات Kotlin (2026)، تجزیه ساختاری حجم کد را هنگام کار با data class تا 30–50٪ کاهش می‌دهد. Destructuring declaration کد را مختصرتر و خواناتر می‌کند.

نکات کلیدی

  • Destructuring declaration — نحو val (a, b) = obj برای تجزیه شی به متغیرها
  • ComponentN() — توابع component1(), component2(), component3() و غیره که به طور خودکار فراخوانی می‌شوند
  • Data class به طور خودکار برای همه ویژگی‌های اعلام‌شده در primary constructor componentN() ایجاد می‌کند
  • Pair و Triple — کلاس‌های استاندارد با تجزیه ساختاری آماده برای دو و سه مقدار
  • Map.Entry — از تجزیه به key و value برای پیمایش راحت پشتیبانی می‌کند

destructuring declaration چیست؟

Destructuring declaration (اعلام تجزیه‌کننده) — یک ساختار نحوی در Kotlin است که به شما امکان می‌دهد یک نمونه از کلاس را در یک عبارت به چند متغیر تجزیه کنید. سمت چپ شامل لیست متغیرها در پرانتز و سمت راست شیء قابل تجزیه است. Kotlin به طور خودکار برای هر متغیر تابع componentN() مناسب را فراخوانی می‌کند، جایی که N شماره ترتیبی متغیر در پرانتز است.

Destructuring declaration اغلب با data class استفاده می‌شود. کامپایلر Kotlin به طور خودکار برای data class توابع component1(), component2() و غیره را بر اساس تعداد ویژگی‌ها در سازنده اولیه ایجاد می‌کند. برای کلاس‌های معمولی بدون اصلاح‌کننده data، componentN() ایجاد نمی‌شود، اما می‌توان آن‌ها را به صورت دستی به عنوان توابع عملگر با کلمه کلیدی operator تعریف کرد.

Destructuring declaration به دلیل توانایی خود در ساده‌سازی کد هنگام کار با مجموعه‌های جفتی، نتایج توابع و پیمایش Map به یک الگوی محبوب تبدیل شده است. به جای نوشتن person.firstName, person.lastName، توسعه‌دهنده می‌نویسد val (firstName, lastName) = person. این کار تعداد خطوط را کاهش می‌دهد و خوانایی را افزایش می‌دهد، به ویژه در حلقه‌ها و لامبداها.

تجزیه ساختاری در Kotlin چگونه کار می‌کند؟

هنگام مواجهه با ساختار val (a, b) = obj، کامپایلر Kotlin کد زیر را تولید می‌کند: val a = obj.component1(); val b = obj.component2(). اگر متغیرها با var اعلام شده باشند، انتساب‌های var تولید می‌شوند. نوع هر متغیر از نوع بازگشتی تابع componentN() مربوطه استنباط می‌شود. این بدان معنی است که destructuring declaration کاملاً نوع-ایمن است و در مرحله کامپایل بررسی می‌شود.

kotlin
data class Person(val firstName: String, val lastName: String, val age: Int)

fun main() {
    val person = Person("Alice", "Smith", 30)

    // Destructuring: component1(), component2(), component3()
    val (firstName, lastName, age) = person
    println("$firstName $lastName, $age سال")
}

در لیستینگ، Person یک data class با سه ویژگی است. Kotlin component1() → firstName، component2() → lastName، component3() → age را تولید می‌کند. عبارت val (firstName, lastName, age) = person این توابع را فراخوانی کرده و نتایج را اختصاص می‌دهد. مهم: نام متغیرها ممکن است با نام ویژگی‌ها مطابقت نداشته باشد — کامپایلر فقط به ترتیب componentN() و انواع آن‌ها نگاه می‌کند. می‌توان فقط N ویژگی اول را تجزیه کرد و بقیه را نادیده گرفت.

تجزیه data class و انواع استاندارد

Data class — کاندید اصلی برای destructuring declaration است. هر data class به طور خودکار برای همه ویژگی‌های سازنده اولیه componentN() دریافت می‌کند. ترتیب componentN() با ترتیب اعلام ویژگی‌ها مطابقت دارد. این بدان معنی است که با تغییر ترتیب فیلدها در data class، ترتیب متغیرها در تجزیه تغییر می‌کند — که می‌تواند منجر به باگ‌های نامرئی شود.

kotlin
// تجزیه Pair
val pair = Pair("key", 42)
val (key, value) = pair
println("$key -> $value")

// تجزیه Triple
val triple = Triple("A", "B", "C")
val (first, second, third) = triple

// Map.Entry در حلقه
val map = mapOf("a" to 1, "b" to 2)
for ((k, v) in map) {
    println("$k = $v")
}

Pair و Triple — کلاس‌های استاندارد با تجزیه ساختاری آماده برای دو و سه جزء. Pair اغلب به عنوان نوع بازگشتی توابعی استفاده می‌شود که باید دو مقدار مرتبط را بدون ایجاد یک data class جداگانه برگردانند. در حلقه for روی Map.Entry، ساختار (k, v) = entry کلید و مقدار را از طریق component1() و component2() تجزیه می‌کند. این یک الگوی استاندارد برای پیمایش Map در Kotlin است که کاملاً جایگزین فراخوانی‌های صریح key و value می‌شود.

زیرخط برای متغیرهای استفاده‌نشده

اگر در تجزیه ساختاری برخی اجزا مورد نیاز نباشند، Kotlin اجازه می‌دهد آن‌ها را با زیرخط _ جایگزین کنید. این کار خوانایی را بهبود می‌بخشد — خواننده بلافاصله می‌بیند که آن جزء نادیده گرفته شده است. علاوه بر این، استفاده از _ از دسترسی تصادفی به متغیر مقداردهی‌نشده جلوگیری می‌کند: کامپایلر هیچ متغیری برای _ ایجاد نمی‌کند، که هشدارهای مربوط به متغیرهای استفاده‌نشده را حذف می‌کند.

kotlin
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("سفارش $id: $amount")
    }
}

در لیستینگ، Order چهار ویژگی دارد، اما در حلقه فقط id و amount مورد نیاز است. زیرخط به جای customerName به کامپایلر می‌گوید «component2() را نادیده بگیر». Kotlin component2() را فراخوانی نمی‌کند و برای این جزء متغیری ایجاد نمی‌کند. مهم: زیرخط فقط در destructuring declaration قابل استفاده است، نه در سازنده data class. اگر چندین جزء متوالی نادیده گرفته شوند، هر کدام زیرخط مخصوص خود را دارند.

ایجاد componentN() برای کلاس‌های سفارشی

برای کلاس‌های بدون اصلاح‌کننده data می‌توان به صورت دستی componentN() را با اضافه کردن کلمه کلیدی operator تعریف کرد. این امکان استفاده از destructuring declaration را با هر کلاسی، از جمله کلاس‌های شخص ثالث که کد منبع آن‌ها قابل تغییر نیست، فراهم می‌کند — کافی است یک تابع extension با operator بنویسید. این رویکرد به ویژه برای کلاس‌های کتابخانه‌ای و کلاس‌های کد Java که componentN() خودکار ندارند مفید است.

kotlin
class Rect(val width: Int, val height: Int)

operator fun Rect.component1(): Int = width
operator fun Rect.component2(): Int = height

// برای کلاس Java با getterها
operator fun Dimension.component1(): Int = width
operator fun Dimension.component2(): Int = height

fun main() {
    val rect = Rect(1920, 1080)
    val (w, h) = rect
    println("رزولوشن: ${w}x${h}")
}

در مثال، Rect یک کلاس معمولی بدون data است. توابع extension با operator fun component1() = width و component2() = height پشتیبانی از تجزیه ساختاری را اضافه می‌کنند. به طور مشابه برای java.awt.Dimension: operator extension روی Dimension امکان تجزیه آن به width و height را فراهم می‌کند. محدودیت: حداکثر تعداد اجزا برای destructuring declaration — 5. در تئوری می‌توان component6() و بالاتر را تعریف کرد، اما Kotlin نحو مناسبی برای 6+ متغیر در پرانتز ایجاد نخواهد کرد.

سوالات متداول

آیا هر data class از تجزیه ساختاری پشتیبانی می‌کند؟

بله، هر data class به طور خودکار برای همه ویژگی‌های سازنده اولیه componentN() دریافت می‌کند. ویژگی‌های اعلام‌شده در بدنه کلاس (از طریق سازنده بدون val/var) componentN() تولید نمی‌کنند.

در صورت عدم تطابق تعداد متغیرها چه اتفاقی می‌افتد؟

اگر در val (a, b, c) = obj شیء فقط دو تابع component داشته باشد، کامپایلر خطا می‌دهد. اگر متغیرها کمتر باشند (val (a) = pair)، Kotlin فقط component1() را فراخوانی کرده و component2() را نادیده می‌گیرد — خطایی رخ نمی‌دهد.

آیا می‌توان Map را بدون حلقه تجزیه ساختاری کرد؟

بله، Map.Entry از تجزیه ساختاری پشتیبانی می‌کند: val (key, value) = map.entries.first(). برای کل Map به طور همزمان تجزیه ساختاری کار نمی‌کند — فقط عنصر به عنصر، در حلقه for یا از طریق iterator.

آیا تجزیه ساختاری در لامبداها کار می‌کند؟

بله، Kotlin از تجزیه ساختاری در پارامترهای لامبدا پشتیبانی می‌کند: map.forEach { (k, v) -> ... }. برای data class در پارامترهای لامبدا باید پرانتزهای تو در تو در اطراف پارامتر اضافه کرد.

حداکثر اندازه تجزیه ساختاری چقدر است؟

Kotlin تا 5 متغیر در destructuring declaration پشتیبانی می‌کند. اگر نیاز به تجزیه بیش از پنج ویژگی دارید، آن‌ها را در data classهای تو در تو ترکیب کنید یا از Pair/Triple در داخل یک متغیر استفاده کنید.

خلاصه

  • Destructuring declaration — نحو val (a, b) = obj، شی را به چند متغیر در یک عبارت تجزیه می‌کند
  • ComponentN() — توابع component1(), component2(), ... که توسط کامپایلر به طور خودکار هنگام تجزیه ساختاری فراخوانی می‌شوند
  • Data class به طور خودکار برای همه ویژگی‌های سازنده اولیه componentN() تولید می‌کند
  • Pair و Triple — کلاس‌های استاندارد با تجزیه ساختاری آماده برای 2 و 3 جزء
  • زیرخط _ اجزای استفاده‌نشده را بدون ایجاد متغیر جایگزین می‌کند
  • Operator componentN() در توابع extension تجزیه ساختاری را به هر کلاسی از جمله Java اضافه می‌کند
  • Map.Entry در حلقه for ((k, v) in map) — الگوی استاندارد اصطلاحی Kotlin برای پیمایش دیکشنری

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید