Protocol trong lập trình Swift
Bài đăng này đã không được cập nhật trong 4 năm
Khái niệm Protocol
Protocol được hiểu là một bản thiết kế bao gồm các thuộc tính, phương thức và các khai báo khác để thực hiện một nhiệm vụ, tính năng nào đó
Protocol có thể được implement bởi một Class, Struct hay Enum.
Khi implement một Protocol, ta sẽ phải khai báo, định nghĩa lại các thuộc tính, phương thức có trong Protocol đó.
Cú pháp khai báo Protocol
Cú pháp khai báo Protocol tương đối giống Class, Struct hay Enum
// Khai báo Protocol
protocol Code {
// Nội dung Protocol khai báo trong đây
}
Muốn Struct, Class hay Enum implement một hoặc nhiều Protocol, ta khai báo như sau
protocol Eat {
}
struct Dev: Code, Eat {
}
Trường hợp khai báo implement cho một Subclass, ta phải để tên của Superclass (Lớp cha) lên trước tên các Protocol
class Human {
}
class Dev: Human, Code, Eat {
}
Khai báo thuộc tính, phương thức trong Protocol
Thuộc tính trong Protocol
Để khai báo thuộc tính trong Protocol, phải có đủ 3 yếu tố
- Tên thuộc tính
- Kiểu dữ liệu
- Trạng thái của thuộc tính (get - get set)
protocol Code {
var experience: Int { get }
var language: String { get set }
}
Lưu ý: Thuộc tính trong Protocol phải khai báo là một var. Do Protocol mặc định những thuộc tính này ở dạng Computed Properties nên không thể khai báo let và phải khai báo thêm trạng thái get hoặc get set
protocol Code {
let level: String { get } // Error: 'let' declarations cannot be computed properties
var experience: Int { get }
var language: String { get set }
}
Protocol hỗ trợ từ khoá "static" để khai báo thuộc tính thuộc về Type thay vì Instance (Protocol không hỗ trợ từ khoá "class")
Phương thức trong Protocol
Khai báo phương thức trong Protocol tương tự với Class, Struct nhưng không có dấu {} và không có nội dung.
Protocol hỗ trợ cả Type Function (khai báo "static") và cả Instance Function
Lưu ý: Protocol không cho phép sử dụng hằng số làm parameter cho phương thức
enum FeelHungry {
case yes
case no
}
protocol Human {
static func talk()
func eat(_ feelHungry: FeelHungry)
func eat2(_ feelHungry: FeelHungry = .yes) // Error: Default argument not permitted in protocol method
}
Nếu Struct hay Enum implement Protocol, mà khi định nghĩa các phương thức, ta muốn thay đổi thuộc tính của nó, ta sẽ phải khai báo thêm từ khoá "mutating" (Do Struct và Enum là kiểu tham trị)
protocol Activities {
mutating func eat()
}
enum State: Activities {
case hungry
case notHungry
mutating func eat() {
switch self {
case .notHungry:
print("Don't need to eat")
case .hungry:
print("Eat something")
self = .notHungry
}
}
}
Optional Protocol
Khi một Protocol chứa rất nhiều phương thức mà không muốn các đối tượng implement Protocol đó phải khai báo lại tất cả, ta sử dụng tới Optional Protocol. Có 2 cách để khai báo Optional Protocol
Cách 1: @objc optional
Khai báo từ khoá @objc optional
trước thuộc tính, phương thức và "@objc" trước khai báo Protocol. Cách khai báo này đưa protocol về trình biên dịch của Objective - C nên chỉ class implement được Protocol này)
@objc protocol OptionalMethodsProtocol {
func mustImplement()
@objc optional var haveNotImplement()
}
class SomeClass: OptionalMethodsProtocol {
func mustImplement() {
}
// Không cần khai báo lại haveNotImplements() do đó là optional
}
Cách 2: Extention Protocol
Đây là cách viết optional protocol phù hợp cho cả Struct, Enum lẫn Class.
Lưu ý: Không khai báo được Stored Properties
protocol OptionalProtocol {
func mustImplement()
}
extension OptionalProtocol {
func haveNotImplement() {
}
}
struct SomeStruct: OptionalProtocol {
func mustImlement() {
}
// Không cần khai báo lại haveNotImplements() do đó là optional
}
Ứng dụng của Protocol
- Protocol có thể sử dụng như một kiểu dữ liệu
- Sử dụng trong Delegate Design Pattern (Sử dụng để "bắt sự kiện", truyền dữ liệu giữa các ViewController")
- Mở rộng đối tượng
- Sử dụng trong nhiều thư viện tiêu chuẩn của Swift (Equable, Comparable, Hasable, Int, ...)
- Lập trình POP (Protocol Oriented Programming)
All rights reserved