Associated Values — กลไกของ Swift ที่อนุญาตให้แนบข้อมูลใด ๆ กับแต่ละเคสของ enum เป็นรายบุคคล ต่างจาก raw values ที่ทุกเคสมีค่าชนิดเดียวกัน associated values สามารถแตกต่างกันทั้งชนิดและจำนวนสำหรับแต่ละเคส ตาม Apple Documentation, 2026 นี่คือความสามารถหลักสำหรับการจำลองโดเมนอย่างแม่นยำโดยไม่ต้องสร้างชนิด wrapper เพิ่มเติม
ประเด็นสำคัญ
Associated Values คือข้อมูลเพิ่มเติมที่เคสของ enum สามารถจัดเก็บไว้กับตัวเองได้ ต่างจาก raw values ที่ถูกกำหนดไว้ที่ระดับการประกาศ associated values จะถูกตั้งค่าเมื่อสร้างอินสแตนซ์ของ enum
ลองนึกภาพการจำลอง วิธีการชำระเงิน: เคส creditCard สามารถจัดเก็บเลข 4 หลักสุดท้ายและวันหมดอายุ ในขณะที่เคส applePay ไม่ได้จัดเก็บอะไรเลย ด้วย associated values สิ่งนี้ถูกนำไปใช้อย่างเป็นธรรมชาติ โดยไม่ต้องมีคลาสย่อยหรือฟิลด์ที่เป็นทางเลือก
ตาม เอกสารของ Apple associated values เปลี่ยน enum จากชุดค่าคงที่ธรรมดาให้เป็นชนิดข้อมูลเชิงพีชคณิต (sum type) ซึ่งเป็นลักษณะเฉพาะของภาษาเชิงฟังก์ชัน ซึ่งช่วยเพิ่มความสามารถในการแสดงออกของโค้ดอย่างมีนัยสำคัญ
Associated Values ถูกประกาศในวงเล็บหลังเคส โดยระบุชื่อและชนิดของพารามิเตอร์ เช่นเดียวกับฟังก์ชัน
enum MediaFile {
case image(width: Int, height: Int, format: String)
case video(duration: Double, codec: String)
case audio(bitrate: Int)
case unknown
}
เมื่อสร้างอินสแตนซ์ associated values จะถูกส่งเป็น อาร์กิวเมนต์:
let photo = MediaFile.image(width: 1920, height: 1080, format: "jpeg")
let clip = MediaFile.video(duration: 120.5, codec: "h264")
Swift ไม่ได้กำหนด ข้อจำกัด เกี่ยวกับจำนวนหรือชนิดของ associated values คุณสามารถใช้ generics, ฟังก์ชันคลอเชอร์ และ enum อื่น ๆ ภายใน associated values ซึ่งทำให้สามารถสร้างโครงสร้างซ้อนที่ซับซ้อนได้
ชื่อพารามิเตอร์ของ associated values ถูกใช้เป็นป้ายกำกับอาร์กิวเมนต์เมื่อสร้างอินสแตนซ์ — ซึ่งช่วยเพิ่มความสามารถในการอ่านโค้ด เมื่อแยกข้อมูลผ่าน switch ชื่อจะทำหน้าที่เป็นเอกสาร ช่วยอธิบายความหมายของแต่ละค่า แนวทางนี้ทำให้โค้ดอธิบายตนเองได้และลดโอกาสเกิดข้อผิดพลาดเมื่อจับคู่ข้อมูล ซึ่งมีค่าเป็นพิเศษในการพัฒนาทีมของแอปพลิเคชัน iOS ขนาดใหญ่
Switch เป็นวิธีหลักในการแยก associated values ค่าจะถูกผูกกับค่าคงที่หรือตัวแปรผ่าน let หรือ var
func describe(_ file: MediaFile) -> String {
switch file {
case .image(let w, let h, let fmt):
return "Image \(w)x\(h) .\(fmt)"
case .video(let duration, let codec):
return "Video \(duration)s, \(codec)"
case .audio(let bitrate):
return "Audio \(bitrate)kbps"
case .unknown:
return "Unknown format"
}
}
Swift รองรับ การจับคู่บางส่วน — คุณสามารถระบุค่าเฉพาะสำหรับ associated values:
switch file {
case .image(let w, let h, "png"):
print("รูปภาพ PNG \(w)x\(h)")
case .image(1920, 1080, _):
print("รูปภาพ Full HD")
default:
break
}
การใช้อักขระ ตัวแทน (_) ช่วยให้ละเว้น associated values ที่ไม่จำเป็น และค่าคงที่ในเคสช่วยให้คุณตรวจสอบการจับคู่กับค่าเฉพาะได้
นักพัฒนามือใหม่หลายคนสับสนระหว่าง associated values กับ raw values ซึ่งเป็นกลไกที่แตกต่างกันพร้อมกรณีการใช้งานที่ต่างกัน
| ลักษณะ | Raw Values | Associated Values |
|---|---|---|
| ชนิดข้อมูล | ชนิดเดียวสำหรับทุกเคส | ชนิดต่างกันสำหรับแต่ละเคส |
| เวลากำหนด | ตอนประกาศ enum | ตอนสร้างอินสแตนซ์ |
| ความจำเป็น | ทุกเคสมีค่า | บางเคสอาจไม่มีค่า |
| ความเข้ากันได้ | กีดกันร่วมกัน — ไม่สามารถใช้พร้อมกันได้ | |
ตาม Swift Evolution associated values ถูกนำมาใช้ใน Swift 2.0 ซึ่งเป็นส่วนหนึ่งของการออกแบบ enum ใหม่ โดยให้แนวทางเชิงพีชคณิตสำหรับชนิดข้อมูลที่แต่ละเคสเป็นตัวสร้างแยกต่างหากพร้อมลายเซ็นของตัวเอง
Associated Values ถูกใช้อย่างแข็งขันในโปรเจกต์ iOS จริง มาดูสามสถานการณ์ทั่วไปกัน
enum APIResponse<T: Codable> {
case success(data: T, cached: Bool)
case failure(error: Error, retryAvailable: Bool)
case loading(progress: Double)
}
enum ViewState<T> {
case idle
case loading(message: String)
case loaded(data: T)
case error(message: String, retryAction: () -> Void)
}
ด้วย associated values enum กลายเป็น เครื่องมือที่มีประสิทธิภาพ สำหรับเครื่องสถานะ: แต่ละเคสคือสถานะ associated values คือพารามิเตอร์ของสถานะนั้น คอมไพเลอร์รับประกันว่าการเปลี่ยนสถานะทั้งหมดได้รับการจัดการ
ในการตรวจสอบเคสเดียวโดยไม่ต้องใช้ switch ให้ใช้ if case หรือ guard case ซึ่งกระชับกว่าเมื่อคุณต้องการจัดการเพียงตัวเลือกเดียว
let error = NetworkError.timeout(seconds: 30)
if case .timeout(let seconds) = error {
print("คำขอหมดเวลาหลังจาก \(seconds)s")
}
guard case .httpError(let code, _) = error else {
return
}
print("ข้อผิดพลาด HTTP ด้วยรหัส \(code)")
คำถามที่พบบ่อย
ได้ เคสสามารถไม่มี associated values — ตัวอย่างเช่น case unknown เคสเหล่านี้ทำงานเหมือนเคส enum ทั่วไปโดยไม่มีข้อมูลเพิ่มเติม ซึ่งสะดวกสำหรับสถานะตัวบ่งชี้
Swift ไม่สร้าง Equatable โดยอัตโนมัติสำหรับ enum ที่มี associated values (ก่อน Swift 4.2+) เพิ่มการ implement Equatable อย่างชัดเจน หรือใช้ switch เพื่อเปรียบเทียบแต่ละเคสตามลำดับ
ได้ associated values ใน indirect enum เป็นเทคนิคมาตรฐานสำหรับการสร้างต้นไม้และรายการเชื่อมโยง เคสสามารถมี associated value ชนิดเดียวกันที่ทำเครื่องหมายด้วย indirect
Associated Values ปลอดภัยต่อชนิด — แต่ละเคสรับประกันว่ามีเฉพาะข้อมูลของตัวเองเท่านั้น ใน struct ที่มีทางเลือก อินสแตนซ์ทุกตัวจะมีทุกฟิลด์และจำเป็นต้องตรวจสอบ nil ในขณะรันไทม์
Swift ไม่สร้าง Codable โดยอัตโนมัติสำหรับ enum ที่มี associated values จำเป็นต้อง implement encode และ decode ด้วยตนเองผ่าน switch บนเคสโดยใช้คีย์การเข้ารหัสแบบกำหนดเอง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ