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 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.
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 (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ạnh | POP (Hướng giao thức) | OOP (Dựa trên lớp) |
|---|---|---|
| Đơn vị trừu tượng | Protocol | Lớp cơ sở |
| Cơ chế tái sử dụng | Protocol extension | Kế thừa |
| Kiểu giá trị | Được hỗ trợ (struct) | Chỉ kiểu tham chiếu |
| Áp dụng nhiều | Protocol composition | Kế thừa nhiều (không có trong Swift) |
| Rủi ro kết nối | Thấ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 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ểm | Swift Protocol | Java Interface | C++ Abstract Class |
|---|---|---|---|
| Triển khai phương thức | Có (extension) | Có (default methods) | Có |
| Thuộc tính lưu trữ | Không | Không | Có |
| Kiểu giá trị | Có | Không | Không |
| Triển khai nhiều | Có | Có | Có |
| Bộ khởi tạo | Có (yêu cầu) | Không | Có |
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 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.
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 — 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.
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 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.
@protocol Loggable
@required
- (void)logMessage: (NSString *)message;
@optional
- (NSString *)logPrefix;
@end
@interface ConsoleLogger : NSObject
@end
@implementation ConsoleLogger
- (void)logMessage: (NSString *)message {
NSLog(@"[LOG] %@", message);
}
@endKhô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
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.
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ã.
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.
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.
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
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.
Đọc thêm