Protocol ใน Swift คือสัญญาที่กำหนดชุดข้อกำหนดที่ทุกประเภทที่รับเอาไปใช้ต้องปฏิบัติตาม โปรโตคอลเป็นรากฐานของการเขียนโปรแกรมแบบโปรโตคอลเป็นหลัก (POP) — กระแสหลักที่ Apple แนะนำสำหรับ Swift คู่กับ OOP แบบดั้งเดิม ตาม Apple Documentation, 2026 โครงสร้าง คลาส และ enum สามารถรับเอาโปรโตคอลไปใช้ ทำให้สถาปัตยกรรมมีความยืดหยุ่นและสามารถทดสอบได้
หัวข้อสำคัญ
Protocol คืออินเทอร์เฟสแบบนามธรรมที่กำหนดว่าชนิดข้อมูลต้องสามารถทำอะไรได้บ้าง แต่ไม่ใช่ว่ามันทำอย่างไร ใน Swift โปรโตคอลเป็นเสมือนกับอินเทอร์เฟสใน Java หรือ Go แต่มีความสามารถเพิ่มเติม
โปรโตคอลสามารถกำหนดได้:
{ get } หรือ { get set }ตาม WWDC 2015 Apple ได้แนะนำการเขียนโปรแกรมแบบโปรโตคอลเป็นหลักเป็นแนวทางพื้นฐานสำหรับสถาปัตยกรรมแอปพลิเคชัน Swift แตกต่างจาก OOP ที่การสืบทอดคลาสสร้างลำดับชั้นแน่นตาย POP นำเสนอการรวมโปรโตคอล ซึ่งให้ความยืดหยุ่น: ชนิดข้อมูลเดียวสามารถประตามโปรโตคอลหลายตัว โดยได้รับข้อกำหนดและการนำไปใช้ผ่านส่วนขยาย
Protocol ประกาศโดยใช้คำสำคัญ protocol ชื่อและเนื้อหา
protocol Drawable {
func draw(context: CGContext)
var boundingBox: CGRect { get }
}
ชนิดข้อมูลรับเอาโปรโตคอลโดยใช้ มหัสยมภาค หลังชื่อ:
struct Circle: Drawable {
let center: CGPoint
let radius: CGFloat
func draw(context: CGContext) {
context.addArc(center: center, radius: radius, ...)
}
var boundingBox: CGRect {
CGRect(x: center.x - radius, y: center.y - radius,
width: radius * 2, height: radius * 2)
}
}
ชนิดข้อมูลเดียวสามารถรับเอา หลายโปรโตคอล โดยคั่นด้วยเครื่องหมายจุลภาค: struct MyType: ProtocolA, ProtocolB ตัวแปลจะตรวจสอบว่าได้ตรงตามข้อกำหนดทั้งหมดของแต่ละโปรโตคอลหรือไม่
ข้อกำหนดคุณสมบัติ ประกาศโดยใช้คำสำคัญ var และตัวระบุการเข้าถึง { get } หรือ { get set }
protocol UserProtocol {
var name: String { get }
var age: Int { get set }
static var maxAge: Int { get }
mutating func updateName(_ newName: String)
}
คำสำคัญ mutating ในโปรโตคอลหมายถึงว่าเมธอดสามารถแก้ไข self ได้ โครงสร้างต้องนำไปใช้เมธอดดังกล่าวเป็น mutating ส่วนคลาสสามารถละเว้นได้ ข้อกำหนดเมธอด ประกาศโดยลายเซ็นเตอร์ที่สมบูรณ์ รวมถึงฉลากพารามิเตอร์
Protocol สามารถสืบทอดโปรโตคอลอื่น และเพิ่มข้อกำหนดใหม่ สร้างลำดับชั้นของสัญญาโดยไม่มีการผูกพันกับคลาสอย่างตายตัว
protocol Vehicle {
var speed: Double { get set }
func move()
}
protocol Flyable: Vehicle {
var altitude: Double { get set }
func takeOff()
}
ชนิดข้อมูลที่รับเอา Flyable ต้องตรงตามข้อกำหนดของทั้งสองโปรโตคอล — Vehicle และ Flyable Swift รองรับการสืบทอดหลายโปรโตคอล: protocol A: B, C
Protocol Composition คือกลไกที่ให้สามารถระบุว่าชนิดข้อมูลต้องประตามโปรโตคอลหลายตัวพร้อมกัน โดยไม่ต้องสร้างโปรโตคอลแบบรวมใหม่
func render(_ item: Drawable & Animatable) {
item.draw(context: ...)
item.animate(duration: 0.3)
}
การรวม (&) ทำงานในพารามิเตอร์ของฟังก์ชัน ตัวแปร และข้อจำกัดเจนิเริก ตัวแปลจะตรวจสอบว่าชนิดข้อมูลที่ส่งเข้าไป ในขณะเดียวกัน ตรงตามโปรโตคอลทั้งหมด การรวมถูกใช้อย่างแพร่หลายใน SwiftUI: some View คือเจนิเริกที่มีการรวม
Protocol Composition ดีกว่าการสร้าง ลำดับชั้นการสืบทอด: แทนที่จะเป็น protocol A: B, C สามารถรับเอา B & C โดยตรง ซึ่งให้ความยืดหยุ่นและลดการผูกพัน การรวมมีประโยชน์เฉพาะในพารามิเตอร์ของฟังก์ชันและข้อจำกัดเจนิเริกที่ต้องการรวมข้อกำหนดชั่วคราวโดยไม่ต้องสร้างโปรโตคอลกลาง ซึ่งจะลดจำนวนชนิดข้อมูลตัวช่วยในโค้ด
Protocol สามารถใช้เป็นชนิดข้อมูลของตัวแปร พารามิเตอร์ของฟังก์ชัน หรือสมาชิกของคอลเลกชัน ที่เรียกว่า existential type
var drawableItem: Drawable
let items: [Drawable] = [Circle(...), Rectangle(...)]
func process(drawables: [any Drawable]) {
for item in drawables {
item.draw(context: ...)
}
}
คำสำคัญ any (Swift 5.6+) ระบุอย่างชัดเจนว่าเป็น existential หากไม่มี any ตัวแปลจะแจ้งเตือน Swift รองรับ some (ชนิดข้อมูลทีบซ้อนไว้) เพื่อซ่อนชนิดข้อมูลที่ตายตัวไว้เบื้องหลังโปรโตคอล — นี่คือแนวทางมาตรฐานใน SwiftUI
เมื่อทำงานกับ โปรโตคอล นักพัฒนามักจะทำผิดพลาดซ้ำๆ หลายอย่าง
Drawable แทน <T: Drawable> ในที่ต้องการชนิดข้อมูลที่ตายตัวAnyObject โดยไม่จำเป็น ซึ่งไม่รวม struct และ enumคำถามที่พบบ่อย
Protocol กำหนดเฉพาะข้อกำหนดโดยไม่มีการนำไปใช้ (จนกระทั่ง protocol extensions) Abstract class สามารถมีการนำไปใช้และสถานะ Swift ไม่มี abstract class — บทนาทของมันถูกดำเนินโดยโปรโตคอลที่มีส่วนขยาย
ได้ โครงสร้าง คลาส และ enum ทั้งหมดสามารถรับเอาโปรโตคอลได้ นี่คือรากฐานของ POP: คุณไม่จำเป็นต้องใช้คลาสเพื่อจัดระเบียบสถาปัตยกรรม โครงสร้างที่มีโปรโตคอลให้คุณสมบัติของค่าและความไม่แปรประกอบ
ชนิดที่เกี่ยวข้อง (associatedtype) คือตัวเก็บตำแหน่งสำหรับชนิดข้อมูลที่ชนิดข้อมูลที่นำไปใช้เป็นผู้กำหนดเอง ตัวอย่าง: Collection มี associatedtype Element ଙี่คือ generic ในระดับโปรโตคอล
ได้ เพิ่มการสืบทอดจาก AnyObject: protocol MyProtocol: AnyObject แล้วเฉพาะคลาสเท่านั้นที่สามารถรับเอาโปรโตคอลนี้ได้ มีประโยชน์สำหรับการอ้างอิงแบบอ่อนและตัวแทน
ใช้ is สำหรับการตรวจสอบและ as? สำหรับการแปลงชนิด: if let drawable = item as? Drawable วิธีนี้ทำงานเฉพาะกับโปรโตคอลที่ไม่มีชนิดที่เกี่ยวข้อง
สรุป
&) รวมโปรโตคอลโดยไม่ต้องสืบทอดany) และ opaque types (some) — สองวิธีการทำงานกับโปรโตคอลเราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ