Struct เป็นชนิดค่า (value type) ในภาษา Swift ซึ่งอินสแตนซ์จะถูกคัดลอกเมื่อส่งผ่านระหว่างส่วนต่าง ๆ ของโค้ด แตกต่างจากคลาส โครงสร้างไม่สนับสนุนการสืบทอด แต่สามารถนำโปรโตคอลมาใช้ มีคุณสมบัติและเมธอด และจัดการหน่วยความจำที่คาดการณ์ได้โดยไม่ต้องใช้ ARC ตาม Swift Programming Language Guide, 2026 struct เป็นส่วนประกอบพื้นฐานของ Swift — แม้แต่ชนิดมาตรฐาน Int, String, Array และ Dictionary ก็ถูกนำมาใช้เป็นโครงสร้าง ภาษาแนะนำให้ใช้โครงสร้างเป็นตัวเลือกหลักสำหรับการสร้างแบบจำลองข้อมูล
ประเด็นสำคัญ
Struct (โครงสร้าง) เป็นชนิดข้อมูลเชิงประกอบใน Swift ที่จัดกลุ่มคุณสมบัติและเมธอดที่เกี่ยวข้องเข้าด้วยกันเป็นเอนทิตีเดียว แตกต่างจากคลาส โครงสร้างเป็น value types: เมื่อส่งผ่านไปยังฟังก์ชันหรือกำหนดให้กับตัวแปรใหม่ จะมีการสร้างสำเนาอิสระของโครงสร้าง ไม่ใช่การอ้างอิงไปยังวัตถุต้นฉบับ
Swift ใช้โครงสร้างสำหรับ ชนิดดั้งเดิม ทั้งหมด: Int, Double, String, Bool, Array, Dictionary และ Set ซึ่งหมายความว่าแม้แต่ Int พื้นฐานก็ทำงานเหมือนโครงสร้าง — จะมีการสร้างสำเนาเมื่อกำหนดค่า นักพัฒนาสามารถกำหนดโครงสร้างของตนเองด้วยชุดคุณสมบัติและเมธอดใดก็ได้
ตาม Swift Evolution (SE-0143) การตัดสินใจนำชนิดมาตรฐานมาใช้เป็นโครงสร้างนั้นขับเคลื่อนด้วยประสิทธิภาพและความสามารถในการคาดเดา Value types ไม่สร้างวงจรอ้างอิง ไม่ต้องนับการอ้างอิง ARC และรับประกันว่าการแก้ไขสำเนาจะไม่ส่งผลต่อต้นฉบับ — ซึ่งสำคัญอย่างยิ่งสำหรับความไม่เปลี่ยนรูปของข้อมูลในสถานการณ์แบบหลายเธรด
ความหมายของ value type คือความแตกต่างหลักระหว่าง struct และ class เมื่อคุณกำหนดโครงสร้างให้กับตัวแปรใหม่หรือส่งผ่านไปยังฟังก์ชัน Swift จะสร้าง สำเนาอิสระ ของข้อมูลทั้งหมด การเปลี่ยนแปลงใด ๆ ในสำเนาจะไม่ส่งผลต่อต้นฉบับ ซึ่งกำจัดผลข้างเคียงทั่วไปของชนิดอ้างอิง
// ตัวอย่างความหมายของ value type
struct Point {
var x: Double
var y: Double
}
var p1 = Point(x: 10, y: 20)
var p2 = p1 // p2 เป็นสำเนาอิสระของ p1
p2.x = 99 // เฉพาะ p2 ที่เปลี่ยนแปลง
print(p1.x) // 10 — p1 ไม่เปลี่ยนแปลง
print(p2.x) // 99
Swift ใช้ Copy-on-Write (COW) เพื่อปรับการคัดลอกให้เหมาะสม หากตัวแปรหลายตัวอ้างอิงถึงโครงสร้างเดียวกันแต่ไม่มีตัวใดแก้ไขข้อมูล จะไม่มีการคัดลอกเกิดขึ้นจริง Swift แบ่งปันหน่วยความจำระหว่างตัวแปรจนกว่าจะมีการเปลี่ยนแปลงครั้งแรก — จากนั้นจึงสร้างสำเนาจริงขึ้นมา ซึ่งป้องกันการจัดสรรที่มากเกินไปและเร่งการทำงานกับคอลเล็กชัน
ตามค่าเริ่มต้น เมธอดของโครงสร้างไม่สามารถเปลี่ยนแปลงคุณสมบัติของมันได้ — Swift ต้องการคำหลัก mutating อย่างชัดเจนสำหรับเมธอดที่ทำการเปลี่ยนแปลง ข้อจำกัดนี้ป้องกันการเปลี่ยนแปลงโดยไม่ตั้งใจและทำให้โค้ดคาดเดาได้: หากเมธอดไม่ได้ถูกทำเครื่องหมายว่า mutating คุณจะได้รับการรับประกันว่าจะไม่เปลี่ยนโครงสร้าง
เมื่อคุณเพิ่มคำหลัก mutating ก่อนเมธอด Swift จะได้รับความสามารถในการเขียนค่าใหม่ลงในคุณสมบัติของโครงสร้าง ที่จริงแล้ว เมธอดสามารถแทนที่อินสแตนซ์ของโครงสร้างทั้งหมดด้วยอินสแตนซ์ใหม่ผ่านทาง self = กลไกนี้ใช้ ตัวอย่างเช่น ในชนิด Option และ Result
// Struct ที่มีเมธอด mutating
struct Counter {
private var value: Int = 0
// เมธอด mutating — สามารถเปลี่ยนแปลงคุณสมบัติได้
mutating func increment() {
value += 1
}
// เมธอด mutating สามารถแทนที่ self ทั้งหมดได้
mutating func reset() {
self = Counter()
}
// เมธอด non-mutating — อ่านอย่างเดียว
func currentValue() -> Int {
return value
}
}
var counter = Counter()
counter.increment()
print(counter.currentValue()) // 1
counter.reset()
print(counter.currentValue()) // 0
กฎสำหรับ mutating: โครงสร้างต้องประกาศด้วย var ไม่ใช่ let — โครงสร้างค่าคงที่ไม่สามารถเรียกเมธอด mutating ได้ คอมไพเลอร์ตรวจสอบสิ่งนี้ในเวลาสร้าง: การพยายามเรียกเมธอด mutating บนค่าคงที่ let จะทำให้เกิดข้อผิดพลาดในการคอมไพล์
การเลือกระหว่าง struct และ class เป็นหนึ่งในการตัดสินใจพื้นฐานใน Swift ทั้งสองชนิดสามารถมีคุณสมบัติ เมธอด ตัวเริ่มต้น และนำโปรโตคอลมาใช้ แต่มีความแตกต่างพื้นฐานในความหมายของหน่วยความจำ การสืบทอด และการจัดการวงจรชีวิต
| คุณลักษณะ | struct | class |
|---|---|---|
| ชนิด | Value type (คัดลอก) | Reference type (อ้างอิง) |
| การสืบทอด | ไม่สนับสนุน | สนับสนุน |
| ARC / การนับการอ้างอิง | ไม่จำเป็น | ARC จำเป็น |
| การสิ้นสุด | ไม่สนับสนุน | สนับสนุน deinit |
| การเปลี่ยนแปลงคุณสมบัติในค่าคงที่ | ผ่าน var เท่านั้น | เป็นไปได้ผ่าน let (การอ้างอิงเป็นค่าคงที่) |
| การแปลงชนิด | ไม่สนับสนุน | สนับสนุน |
| การเก็บในคอลเล็กชัน | เก็บโดยตรง (ค่า) | เก็บเป็นข้อมูลอ้างอิง (พอยน์เตอร์) |
โครงสร้างเป็นที่นิยมเมื่อข้อมูล ไม่ต้องการการสืบทอด ไม่ควรมีเอกลักษณ์ร่วมกัน (เช่น พิกัด ขนาด การกำหนดค่า) และถูกส่งระหว่างโมดูล คลาสถูกเลือกสำหรับส่วนประกอบ UI (UIView, UIViewController), ซิงเกิลตัน และวัตถุที่มีเอกลักษณ์ร่วมกัน
Apple แนะนำให้ใช้ struct เป็น ชนิดเริ่มต้น สำหรับการสร้างแบบจำลองข้อมูลใน Swift โครงสร้างเหมาะสำหรับสถานการณ์ส่วนใหญ่เนื่องจากความหมายการคัดลอกที่คาดเดาได้และไม่มีภาระการนับการอ้างอิง มาดูกรณีทั่วไปที่ struct เป็นตัวเลือกที่เหมาะสมที่สุด
หากเอนทิตีมีข้อมูลโดยไม่จำเป็นต้องสืบทอด (Product, User, Order, Point) ให้ใช้ struct คอมไพเลอร์จะสร้าง memberwise initializer โดยอัตโนมัติ — คุณไม่จำเป็นต้องเขียน init ด้วยตนเอง Equatable และ Hashable ก็ถูกนำมาใช้โดยอัตโนมัติสำหรับโครงสร้างที่คุณสมบัติทั้งหมดเป็นไปตามโปรโตคอลเหล่านี้
สำหรับการกำหนดค่า การตั้งค่า และแฟล็กที่ไม่เปลี่ยนแปลงหลังจากการสร้าง struct ดีกว่า class โครงสร้างค่าคงที่ (let) รับประกันความไม่เปลี่ยนรูปของฟิลด์ที่ซ้อนกันทั้งหมด — ใน class สิ่งนี้ใช้เฉพาะกับการอ้างอิงเท่านั้น ไม่ใช่เนื้อหาของวัตถุ
โครงสร้างปลอดภัยในสภาพแวดล้อมแบบหลายเธรดเนื่องจากความหมายของค่า แต่ละเธรดได้รับสำเนาข้อมูลอิสระและไม่ส่งผลต่อเธรดอื่น การแข่งขันของข้อมูล ระหว่างเธรดเป็นไปไม่ได้สำหรับ value types ทำให้ struct เป็นตัวเลือกที่ต้องการสำหรับแบบจำลองใน SwiftUI (ObservableObject ต้องใช้ class แต่ @State ใช้ struct)
// ตัวอย่างการใช้ struct สำหรับแบบจำลองข้อมูล
struct User: Codable, Identifiable {
let id: UUID
var name: String
var email: String
var isPremium: Bool
// คุณสมบัติที่คำนวณ — non-mutating
var displayName: String {
isPremium ? "\(name) ⭐️" : name
}
}
// ตัวเริ่มต้น memberwise อัตโนมัติ
let user = User(
id: UUID(),
name: "Alice",
email: "alice@example.com",
isPremium: true
)
// การคัดลอกปลอดภัยสำหรับการทำงานแบบหลายเธรด
var userCopy = user
userCopy.isPremium = false
// user.isPremium ยังคงเป็น true
ใช้ class เมื่อคุณต้องการ การสืบทอด (ส่วนประกอบ UIKit/AppKit) เอกลักษณ์ร่วมกัน (delegate, observer) หรือวงจรชีวิตวัตถุที่ควบคุมได้ (deinit) สำหรับสิ่งอื่นทั้งหมด — ให้ใช้ struct
คำถามที่พบบ่อย
Struct ใน Swift เป็นชนิดค่าที่ถูกคัดลอกเมื่อส่งผ่านระหว่างส่วนต่าง ๆ ของโค้ด โครงสร้างสามารถมีคุณสมบัติ เมธอด ตัวเริ่มต้น และนำโปรโตคอลมาใช้ ชนิดพื้นฐานของ Swift (Int, String, Array) ถูกนำมาใช้เป็นโครงสร้าง
Struct เป็น value type (คัดลอกเมื่อกำหนดค่า) ไม่สนับสนุนการสืบทอดและไม่ต้องการ ARC Class เป็น reference type (ส่งผ่านโดยการอ้างอิง) สนับสนุนการสืบทอด การสิ้นสุด และการนับการอ้างอิง นักพัฒนาแนะนำให้ใช้ struct เป็นชนิดเริ่มต้น
Mutating เป็นคำหลักที่บ่งชี้ว่าเมธอดของโครงสร้างสามารถเปลี่ยนแปลงคุณสมบัติของมันได้ หากไม่มี mutating คอมไพเลอร์จะห้ามการแก้ไขฟิลด์ เมธอด mutating สามารถเรียกได้เฉพาะกับตัวแปรที่ประกาศด้วย var เท่านั้น ไม่ใช่ let
Copy-on-Write (COW) เป็นการปรับให้เหมาะสมของ Swift สำหรับโครงสร้างซึ่งการคัดลอกข้อมูลจริงจะถูกเลื่อนออกไปจนกว่าจะมีการเปลี่ยนแปลงครั้งแรก ตราบใดที่ตัวแปรทั้งหมดอ่านโครงสร้างเท่านั้น พวกมันจะแบ่งปันพื้นที่หน่วยความจำเดียวกัน สิ่งนี้ช่วยเพิ่มประสิทธิภาพเมื่อทำงานกับคอลเล็กชันขนาดใหญ่
ใช้ struct สำหรับแบบจำลองข้อมูลที่ไม่ต้องการการสืบทอด การกำหนดค่า DTO และสถานการณ์แบบหลายเธรด ใช้ class สำหรับส่วนประกอบ UI UIKit/AppKit, ซิงเกิลตัน, เอนทิตีที่มีเอกลักษณ์ร่วมกัน (delegate, observer) และวัตถุที่ต้องการการสิ้นสุด
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ