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 สร้าง componentN() โดยอัตโนมัติสำหรับคุณสมบัติทั้งหมดที่ประกาศใน primary constructor
  • Pair และ Triple — คลาสมาตรฐานที่มีการแยกตัวแปรพร้อมใช้สำหรับค่าสองและสามค่า
  • Map.Entry — รองรับการแยกเป็น key และ value เพื่อการวนซ้ำที่สะดวก

destructuring declaration คืออะไร?

Destructuring declaration (การประกาศแบบแยกโครงสร้าง) คือโครงสร้างไวยากรณ์ของ Kotlin ที่ช่วยให้แยกอินสแตนซ์ของคลาสออกเป็นตัวแปรหลายตัวในนิพจน์เดียว ด้านซ้ายมีรายการตัวแปรในวงเล็บ ด้านขวาคือวัตถุที่จะถูกแยก Kotlin จะเรียกฟังก์ชัน componentN() ที่สอดคล้องกันโดยอัตโนมัติสำหรับแต่ละตัวแปร โดยที่ N คือลำดับของตัวแปรในวงเล็บ

destructuring declaration มักถูกใช้กับ data class มากที่สุด คอมไพเลอร์ของ Kotlin จะสร้างฟังก์ชัน component1(), component2() และอื่น ๆ สำหรับ data class โดยอัตโนมัติตามจำนวนคุณสมบัติในคอนสตรัคเตอร์หลัก สำหรับคลาสทั่วไปที่ไม่มีตัวปรับเปลี่ยน 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)

    // การแยกโครงสร้าง: 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 function ที่มี 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 ที่มี getters
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 หรือผ่านตัววนซ้ำ

การแยกโครงสร้างทำงานในแลมบ์ดาหรือไม่?

ได้ 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 สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม