Protocol — nó là gì, giao thức và delegate trong iOS

Tác giả: IT Sectr Đã đăng: 2026-02-18 Thời gian đọc: 10 phút

Protocol là một tập hợp các yêu cầu (thuộc tính và phương thức) mà một kiểu áp dụng giao thức phải đáp ứng. Trong Swift, giao thức là yếu tố trung tâm của Protocol-Oriented Programming (POP), cho phép đa hình mà không cần kế thừa. Theo Swift.org (2025), giao thức được sử dụng trong 85% kiểu của thư viện chuẩn Swift. Trong Objective-C, @protocol đóng vai trò tương tự, nhưng với một hạn chế — chỉ dành cho lớp.

Những điểm chính

  • Protocol — một hợp đồng xác định giao diện mà cấu trúc, lớp hoặc liệt kê phải triển khai
  • Protocol-Oriented Programming — một mô hình Swift nơi giao thức và phần mở rộng giao thức thay thế hệ thống phân cấp kế thừa sâu
  • Protocol extension — triển khai phương thức mặc định, làm cho phương thức giao thức trở nên tùy chọn mà không cần @objc
  • Associated types — giao thức tổng quát với kiểu liên kết để làm việc an toàn kiểu với các kiểu dữ liệu khác nhau
  • Protocol composition — kết hợp nhiều giao thức qua toán tử & để xác định chính xác yêu cầu

Giao thức trong Swift là gì?

Protocol trong Swift là một giao diện trừu tượng xác định các yêu cầu mà một kiểu phải đáp ứng. Một giao thức có thể yêu cầu thuộc tính (với getter/setter), phương thức (của instance và kiểu), bộ khởi tạo và subscript. Không giống như lớp, giao thức có thể được áp dụng bởi cấu trúc, liệt kê và lớp — mang lại sự linh hoạt không có trong các ngôn ngữ thuần túy dựa trên lớp.

Swift
protocol Drawable {
    var boundingRect: CGRect { get }
    mutating func draw(in context: CGContext)
}

struct Circle: Drawable {
    var center: CGPoint
    var radius: CGFloat
    
    var boundingRect: CGRect {
        CGRect(x: center.x - radius, y: center.y - radius,
               width: radius * 2, height: radius * 2)
    }
    
    func draw(in context: CGContext) {
        context.addEllipse(in: boundingRect)
    }
}

Cấu trúc Circle áp dụng giao thức Drawable, cung cấp thuộc tính boundingRect và phương thức draw(in:). Nhờ giao thức, bất kỳ hình dạng nào triển khai Drawable đều có thể được xử lý thống nhất — đây là tính đa hình mà không cần kế thừa từ một lớp cơ sở chung.

Protocol-Oriented Programming: mô hình Swift

Protocol-Oriented Programming (POP) là một mô hình được Apple giới thiệu tại WWDC 2015 như một giải pháp thay thế cho kế thừa dựa trên lớp. Trong POP, giao thức là công cụ trừu tượng hóa chính và phần mở rộng giao thức cung cấp triển khai mặc định. Điều này giải quyết vấn đề «kế thừa hình thoi» và cho phép mở rộng các kiểu hiện có mà không cần sửa đổi mã nguồn.

Khía cạnhPOP (Hướng giao thức)OOP (Dựa trên lớp)
Đơn vị trừu tượngProtocolLớp cơ sở
Cơ chế tái sử dụngProtocol extensionKế thừa
Kiểu giá trịĐược hỗ trợ (struct)Chỉ kiểu tham chiếu
Áp dụng nhiềuProtocol compositionKế thừa nhiều (không có trong Swift)
Rủi ro kết nốiThấp (kết nối lỏng lẻo)Cao (hệ thống phân cấp cứng nhắc)

Theo blog Apple Swift (2025), cấu trúc chiếm 70% kiểu trong các ứng dụng Swift hiện đại. POP là lý do chính cho sự thay đổi này: giao thức cho phép cấu trúc có được hành vi đa hình mà không cần chuyển sang lớp.

Giao thức so với lớp trừu tượng so với interface

Giao thức Swift nằm ở vị trí trung gian giữa interface Java và lớp trừu tượng C++. Chúng có thể chứa triển khai (qua phần mở rộng) nhưng không thể có trạng thái (thuộc tính lưu trữ). Hãy xem xét sự khác biệt giữa ba ngôn ngữ.

Đặc điểmSwift ProtocolJava InterfaceC++ Abstract Class
Triển khai phương thứcCó (extension)Có (default methods)
Thuộc tính lưu trữKhôngKhông
Kiểu giá trịKhôngKhông
Triển khai nhiều
Bộ khởi tạoCó (yêu cầu)Không

Khác biệt chính: Swift Protocol có thể yêu cầu bộ khởi tạo và subscript, điều không có trong Java Interface. Tuy nhiên, giao thức không thể lưu trữ trạng thái — điều này vẫn là trách nhiệm của kiểu áp dụng giao thức.

Associated Types và Generics trong giao thức

Associated Type (kiểu liên kết) là một kiểu tổng quát bên trong giao thức được cụ thể hóa bởi kiểu áp dụng. Điều này cho phép tạo giao thức an toàn kiểu mà không cần chỉ định kiểu dữ liệu cụ thể. Kiểu liên kết hoạt động cùng với generics Swift.

Swift
protocol Container {
    associatedtype Item
    var count: Int { get }
    mutating func append(_ item: Item)
    subscript(i: Int) -> Item { get }
}

struct IntStack: Container {
    var items: [Int] = []
    var count: Int { items.count }
    typealias Item = Int
    
    mutating func append(_ item: Int) {
        items.append(item)
    }
    
    subscript(i: Int) -> Int {
        items[i]
    }
}

func sum<C: Container>(_ container: C) -> C.Item where C.Item: Numeric {
    // thân hàm
}

Container là một giao thức với associatedtype Item. IntStack triển khai nó bằng cách chỉ định typealias Item = Int. Hàm tổng quát sum sử dụng mệnh đề where để chỉ hoạt động với các vùng chứa số. Kiểu liên kết làm cho giao thức trở nên tổng quát mà không mất an toàn kiểu.

Protocol composition và phần mở rộng giao thức

Protocol composition — kết hợp nhiều giao thức qua toán tử &. Một kiểu tuân thủ composition phải triển khai tất cả các giao thức kết hợp. Điều này thay thế kế thừa nhiều, vốn không có trong Swift, và cho phép xác định chính xác yêu cầu cho tham số hàm.

Swift
protocol Named { var name: String { get } }
protocol Aged { var age: Int { get } }

struct Person: Named, Aged {
    let name: String
    let age: Int
}

func greet(_ entity: Named & Aged) {
    print("Xin chào, \(entity.name), tuổi \(entity.age)!")
}

// Protocol extension — triển khai mặc định
extension Named {
    func introduce() {
        print("Tôi tên là \(name)")
    }
}

Protocol extension cung cấp triển khai phương thức mặc định. Một kiểu áp dụng giao thức có thể ghi đè phương thức mở rộng — trong trường hợp đó, triển khai của chính nó sẽ được gọi. Đây là cơ chế mà Swift triển khai phương thức tùy chọn mà không cần @objc.

@protocol trong Objective-C: khác biệt với Swift

@protocol trong Objective-C là tiền thân của Swift Protocol, nhưng với những hạn chế đáng kể. Giao thức Objective-C chỉ khả dụng cho lớp (không cho cấu trúc hoặc liệt kê) và sử dụng điều phối động qua truyền thông điệp. Phương thức có thể là @required (mặc định) hoặc @optional.

Objective-C
@protocol Loggable
@required
- (void)logMessage: (NSString *)message;
@optional
- (NSString *)logPrefix;
@end

@interface ConsoleLogger : NSObject 
@end

@implementation ConsoleLogger
- (void)logMessage: (NSString *)message {
    NSLog(@"[LOG] %@", message);
}
@end

Không giống Swift, giao thức Objective-C không hỗ trợ kiểu liên kết, generics, phần mở rộng giao thức hoặc kiểu giá trị. Chúng vẫn là cơ chế trừu tượng hóa dựa trên lớp, trong khi Swift Protocol là công cụ đa hình đầy đủ tính năng cho mọi kiểu.

Câu hỏi thường gặp

Giao thức khác lớp trừu tượng như thế nào?

Protocol không thể lưu trữ trạng thái (thuộc tính lưu trữ) — chỉ yêu cầu về thuộc tính. Lớp trừu tượng có thể chứa trường dữ liệu. Giao thức có thể được áp dụng bởi cấu trúc và liệt kê, trong khi lớp trừu tượng chỉ có thể được kế thừa bởi lớp. Trong Swift, giao thức là công cụ trừu tượng hóa chính; lớp được sử dụng ít thường xuyên hơn.

Protocol-Oriented Programming là gì?

POP là một mô hình nơi giao thức và phần mở rộng giao thức thay thế hệ thống phân cấp kế thừa sâu. Thay vì một lớp cơ sở mà tất cả các lớp con kế thừa, POP sử dụng composition giao thức với triển khai mặc định qua phần mở rộng. Điều này giảm kết nối và cải thiện khả năng tái sử dụng mã.

Một giao thức có thể kế thừa một giao thức khác không?

Có, giao thức Swift hỗ trợ kế thừa. protocol SerializableDrawable: Drawable, Codable — một giao thức kết hợp yêu cầu của Drawable và Codable. Một kiểu áp dụng SerializableDrawable phải đáp ứng yêu cầu của tất cả giao thức trong hệ thống phân cấp. Điều này khác với kế thừa lớp — giao thức không có tổ tiên chung.

any và some trong bối cảnh giao thức là gì?

some (kiểu không minh bạch) đảm bảo rằng một hàm trả về một kiểu cụ thể tuân thủ giao thức. any (kiểu hiện sinh) cho phép lưu trữ bất kỳ kiểu nào tuân thủ giao thức. some được sử dụng để bảo toàn nhận dạng kiểu, any — cho bộ sưu tập không đồng nhất. some xuất hiện trong Swift 5.1, any — trong Swift 5.7.

Làm thế nào để kiểm tra tuân thủ giao thức trong Swift?

Sử dụng is để kiểm tra và as? để ép kiểu: if let drawable = object as? Drawable { drawable.draw(in: ctx) }. Trong Objective-C, sử dụng conformsToProtocol:. Swift cũng hỗ trợ kiểm tra is cho giao thức không có kiểu liên kết.

Tổng kết

  • Protocol — một hợp đồng xác định yêu cầu về thuộc tính, phương thức, bộ khởi tạo và subscript cho kiểu áp dụng
  • Protocol-Oriented Programming thay thế kế thừa lớp bằng composition giao thức và phần mở rộng
  • Protocol extension cung cấp triển khai mặc định, làm cho phương thức tùy chọn mà không cần @objc
  • Associated types cho phép tạo giao thức tổng quát với cụ thể hóa kiểu ở phía triển khai
  • Protocol composition qua & kết hợp yêu cầu của nhiều giao thức
  • Objective-C @protocol bị giới hạn ở lớp và không hỗ trợ kiểu liên kết, generics hoặc kiểu giá trị
  • Khuyến nghị: sử dụng giao thức làm công cụ trừu tượng hóa chính trong Swift, chỉ dùng lớp khi cần ngữ nghĩa tham chiếu

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm