Protocol ใน Swift — มันคืออะไร ไวยากรณ์และความสามารถ

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-17 เวลาอ่าน: 6 นาที

Protocol ใน Swift คือสัญญาที่กำหนดชุดข้อกำหนดที่ทุกประเภทที่รับเอาไปใช้ต้องปฏิบัติตาม โปรโตคอลเป็นรากฐานของการเขียนโปรแกรมแบบโปรโตคอลเป็นหลัก (POP) — กระแสหลักที่ Apple แนะนำสำหรับ Swift คู่กับ OOP แบบดั้งเดิม ตาม Apple Documentation, 2026 โครงสร้าง คลาส และ enum สามารถรับเอาโปรโตคอลไปใช้ ทำให้สถาปัตยกรรมมีความยืดหยุ่นและสามารถทดสอบได้

หัวข้อสำคัญ

  • Protocol — สัญญาที่มีข้อกำหนดสำหรับโครงสร้าง คลาส และ enum
  • ข้อกำหนด รวมถึงเมธอด คุณสมบัติ ตัวเริ่มต้น และ subscript
  • Protocol Composition อนุญาตให้รวมหลายโปรโตคอล
  • POP — การเขียนโปรแกรมแบบโปรโตคอลเป็นหลัก ทดแทนการสืบทอด
  • Protocol Extensions เพิ่มการนำไปใช้แบบเริ่มต้นสำหรับเมธอด

Protocol ใน Swift คืออะไร?

Protocol คืออินเทอร์เฟสแบบนามธรรมที่กำหนดว่าชนิดข้อมูลต้องสามารถทำอะไรได้บ้าง แต่ไม่ใช่ว่ามันทำอย่างไร ใน Swift โปรโตคอลเป็นเสมือนกับอินเทอร์เฟสใน Java หรือ Go แต่มีความสามารถเพิ่มเติม

โปรโตคอลสามารถกำหนดได้:

  • เมธอด แบบอินสแตนซ์และแบบชนิด (สถิต)
  • คุณสมบัติ ด้วยตัวระบุ { get } หรือ { get set }
  • ตัวเริ่มต้น
  • Subscript
  • ชนิดที่เกี่ยวข้อง (เจนิเริกในระดับโปรโตคอล)

ตาม WWDC 2015 Apple ได้แนะนำการเขียนโปรแกรมแบบโปรโตคอลเป็นหลักเป็นแนวทางพื้นฐานสำหรับสถาปัตยกรรมแอปพลิเคชัน Swift แตกต่างจาก OOP ที่การสืบทอดคลาสสร้างลำดับชั้นแน่นตาย POP นำเสนอการรวมโปรโตคอล ซึ่งให้ความยืดหยุ่น: ชนิดข้อมูลเดียวสามารถประตามโปรโตคอลหลายตัว โดยได้รับข้อกำหนดและการนำไปใช้ผ่านส่วนขยาย

ไวยากรณ์การประกาศโปรโตคอล

Protocol ประกาศโดยใช้คำสำคัญ protocol ชื่อและเนื้อหา

swift
protocol Drawable {
    func draw(context: CGContext)
    var boundingBox: CGRect { get }
}

ชนิดข้อมูลรับเอาโปรโตคอลโดยใช้ มหัสยมภาค หลังชื่อ:

swift
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 }

swift
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 สามารถสืบทอดโปรโตคอลอื่น และเพิ่มข้อกำหนดใหม่ สร้างลำดับชั้นของสัญญาโดยไม่มีการผูกพันกับคลาสอย่างตายตัว

swift
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

Protocol Composition คือกลไกที่ให้สามารถระบุว่าชนิดข้อมูลต้องประตามโปรโตคอลหลายตัวพร้อมกัน โดยไม่ต้องสร้างโปรโตคอลแบบรวมใหม่

swift
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

swift
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

ข้อผิดพลาดทั่วไปกับโปรโตคอล

เมื่อทำงานกับ โปรโตคอล นักพัฒนามักจะทำผิดพลาดซ้ำๆ หลายอย่าง

  • ลืม mutating — เมธอดถูกทำเครื่องหมายว่า mutating ในโปรโตคอล แต่โครงสร้างนำไปใช้โดยไม่มีคำสำคัญ
  • ใช้โปรโตคอลเป็นชนิดแทน generic — ใช้ Drawable แทน <T: Drawable> ในที่ต้องการชนิดข้อมูลที่ตายตัว
  • การอ้างอิงโปรโตคอลแบบวงจร — โปรโตคอลที่อ้างถึงตัวเองผ่านชนิดที่เกี่ยวข้องโดยไม่มีการแก้ไขที่ถูกต้อง
  • โปรโตคอลสำหรับคลาสเท่านั้น — ใช้ AnyObject โดยไม่จำเป็น ซึ่งไม่รวม struct และ enum

คำถามที่พบบ่อย

Protocol แตกต่างจาก abstract class อย่างไร?

Protocol กำหนดเฉพาะข้อกำหนดโดยไม่มีการนำไปใช้ (จนกระทั่ง protocol extensions) Abstract class สามารถมีการนำไปใช้และสถานะ Swift ไม่มี abstract class — บทนาทของมันถูกดำเนินโดยโปรโตคอลที่มีส่วนขยาย

struct สามารถรับเอา protocol ได้หรือไม่?

ได้ โครงสร้าง คลาส และ enum ทั้งหมดสามารถรับเอาโปรโตคอลได้ นี่คือรากฐานของ POP: คุณไม่จำเป็นต้องใช้คลาสเพื่อจัดระเบียบสถาปัตยกรรม โครงสร้างที่มีโปรโตคอลให้คุณสมบัติของค่าและความไม่แปรประกอบ

ชนิดที่เกี่ยวข้องในโปรโตคอลคืออะไร?

ชนิดที่เกี่ยวข้อง (associatedtype) คือตัวเก็บตำแหน่งสำหรับชนิดข้อมูลที่ชนิดข้อมูลที่นำไปใช้เป็นผู้กำหนดเอง ตัวอย่าง: Collection มี associatedtype Element ଙี่คือ generic ในระดับโปรโตคอล

ฉันสามารถจำกัดโปรโตคอลให้ใช้กับคลาสเท่านั้นได้หรือไม่?

ได้ เพิ่มการสืบทอดจาก AnyObject: protocol MyProtocol: AnyObject แล้วเฉพาะคลาสเท่านั้นที่สามารถรับเอาโปรโตคอลนี้ได้ มีประโยชน์สำหรับการอ้างอิงแบบอ่อนและตัวแทน

จะตรวจสอบการประตามโปรโตคอลในขณะที่ทำงานได้อย่างไร?

ใช้ is สำหรับการตรวจสอบและ as? สำหรับการแปลงชนิด: if let drawable = item as? Drawable วิธีนี้ทำงานเฉพาะกับโปรโตคอลที่ไม่มีชนิดที่เกี่ยวข้อง

สรุป

  • Protocol — สัญญาสำหรับเมธอด คุณสมบัติ ตัวเริ่มต้น และ subscript
  • Class, struct, enum — ทุกชนิดข้อมูลสามารถรับเอาโปรโตคอลได้
  • การสืบทอด ของโปรโตคอลสร้างลำดับชั้นของสัญญาโดยไม่มีความผูกพันที่ตายตัว
  • Protocol Composition (&) รวมโปรโตคอลโดยไม่ต้องสืบทอด
  • Existential types (any) และ opaque types (some) — สองวิธีการทำงานกับโปรโตคอล
  • POP ได้รับการแนะนำจาก Apple เป็นทางเลือกแทนการสืบทอดคลาสแบบดั้งเดิม
  • Protocol Extensions อนุญาตให้เพิ่มการนำไปใช้แบบเริ่มต้น

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

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

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