Trong bài học trước, bạn đã được học “kỹ thuật mở rộng class bằng Extension“. Đây là một kỹ thuật rất hay để mở rộng một class nào đó dù cho bạn không nắm mã nguồn. Để nâng cao hơn trong việc thao tác với class, bài viết này mình sẽ trình bày tới bạn một thành phần mới cho phép bạn khai báo các qui tắc giao tiếp chung cho class, đó là protocol. Nếu bạn đã học Objective C thì sẽ không xa lạ với protocol, thế nhưng protocol trong Swift thì sao? Có gì giống và khác với protocol trong Objective hay không?
Protocol là gì
Protocol là thành phần trừu tượng cho phép bạn khai báo danh sách các phương thức và thuộc tính nhưng không cài đặt các phương thức này.
Protocol được sử dụng làm lớp cơ sở cho bất kỳ class, struct, enum nào cũng có thể áp dụng thực thi. Class, struct, enum áp dụng protocol sẽ cài đặt các phương thức được khai báo trong protocol.
Cú pháp khai báo và thực thi protocol
Việc khai báo protocol cũng tương tự như bạn khai báo một class, bạn tuân thủ theo cú pháp sau:
Tương tự, để áp dụng thực thi một protocol bạn sử dụng toán tử “:” tương tự việc kế thừa:
Hai cú pháp trên bạn có thấy quen không nào? Rất giống việc khai báo class và thực hiện kế thừa cho class phải không? Thực tế thì làm việc với protocol cũng tương tự như làm việc với class thôi bạn ạ. Chỉ khác là bạn sẽ không cần phải cài đặt các phương thức của protocol mà bạn đã khai báo.
Ví dụ
Chúng ta sẽ cùng nhau xây dựng protocol StreetLegal như hình minh hoạ bên dưới:
Mình sẽ mô tả sơ đồ trên một xíu nhé. StreetLegal là protocol khai báo qui tắc luật giao thông đường bộ chung cho các phương tiện bộ hành.
- Lớp Car, Bicycle, Pedestrian sẽ áp dụng thực thi protocol StreetLegal.
➤ Lưu ý: luật đường bộ của Car sẽ khác Bicycle và Pedestrian vì vậy bạn sẽ cần định nghĩa qui tắc luật đường bộ riêng cho phù hợp với mỗi loại phương tiện này. - Boat và Car cũng là phương tiện nhưng Boat là phương tiện đường thuỷ nên không thể sử áp dụng qui tắc đường bộ như Car.
Thuộc tính và phương thức
Bây giờ, chúng ta hãy cùng nhau tìm hiểu cách thức khai báo thuộc tính và phương thức cho protocol bằng cách làm luôn ví dụ ở trên nhé.
Khai báo thuộc tính
Việc khai báo thuộc tính cho protocol tương tự như khai báo thuộc tính cho class. Tuy nhiên, protocol yêu cầu chỉ rõ thuộc tính read-only hay thuộc tính thông thường.
➤ Ví dụ: mình sẽ xây dựng protocol StreetLegal và khai báo thuộc tính như sau.
Cách thức khai báo tương tự class, ngoại trừ việc bắt buộc phải chỉ định set/get. Bạn hãy lưu ý những phần mình ghi chú trong ví dụ trên nhé. Những ghi chú đó là những gợi ý để giúp bạn xác định nên khai báo thuộc tính là hằng hay biến.
Khai báo phương thức
Khai báo phương thức trong protocol tương tự khai báo hàm thông thường, nhưng không cài đặt. Việc cài đặt các phương thức này sẽ được class/struct/enum nào áp dụng thực hiện.
Ngoài ra, protocol cũng cho phép khai báo phương thức mutating để hỗ trợ người dùng thực hiện việc thay đổi giá trị nội tại của class/struct/enum thực thi protocol.
➤ Ví dụ: mình sẽ tiếp tục khai báo phương thức cho protocol StreetLegal như sau.
Áp dụng thực thi protocol
Bây giờ chính là lúc để bạn thử sử dụng protocol StreetLegal đã được khai báo ở 02 phần trên. Nhìn lại sơ đồ trên, chúng ta sẽ có 03 class Car, Bicycle, Pedestrian sẽ áp dụng protocol StreetLegal. Bây giờ mình sẽ làm mẫu một class, sau đó bạn hãy thử làm tiếp với hai class còn lại.
➤ Ví dụ: mình sẽ xây dựng lớp Bicycle áp dụng protocol StreetLegal như sau.
Bạn thấy không, class Bicycle áp dụng protocol StreetLegal do đó class này cần phải thực hiện cài đặt nội dung cho các phương thức mẫu của protocol StreetLegal. Đồng thời bạn cũng có thể thiết lập giá trị cho các thuộc tính của protocol StreetLegal tại đây. Tương tự, bạn hãy thực hiện xây dựng class Car và Pedestrian nhé.
Phương thức khởi tạo
Tương tự class, protocol trong Swift cũng cho phép bạn khai báo các phương thức khởi tạo (init) mẫu. Và bạn cũng cần lưu ý là, đối tượng nào (class/struct/enum) áp dụng protocol đều phải cài đặt các phương thức khởi tạo này.
Cú pháp khai báo cũng tương tự class, ví dụ:
➤ Lưu ý: class nào áp dụng protocol thì phải thêm từ khoá required khi cài đặt phương thức khởi tạo. Riêng struct/enum hoặc final class thì không cần. Ví dụ như sau:
➤ Ghi chú: final class là class không bao giờ có subclass (class con kế thừa).
Một số tính chất khác của protocol
Optional Protocol Requirements
Mặc định khi một class thực thi protocol thì phải cài đặt lại tất cả các thuộc tính và phương thức của protocol.
➤ Vấn đề: giả sử protocol có quá nhiều phương thức và không phải phương thức nào cũng được sử dụng. Không lẽ chúng ta cũng phải cài đặt hết các phương thức không sử dụng đó luôn sao?
➤ Giải pháp: Swift cho phép bạn cấu hình một số thuộc tính hoặc phương thức optional. Những thuộc tính hoặc phương thức này có thể được cài đặt hoặc không cần cài đặt trong đối tượng nào áp dụng protocol.
Để khai báo thuộc tính hoặc phương thức optional, bạn cần thêm từ khoá @objc optional trước protocol. Ví dụ:
Trong ví dụ trên, hàm signalRightTurn được khai báo là optional, do đó bạn có thể không cần cài đặt hàm này nếu muốn.
Protocol Extension
Tương tự như class, bạn cũng có thể tạo đối tượng extension để mở rộng bổ sung thêm thuộc tính hoặc phương thức cho một protocol nào đó.
➤ Ví dụ: mình sẽ thử xây dựng extension để bổ sung thêm phương thức cho protocol StreetLegal như sau.
➤ Lưu ý: nếu bổ sung thêm phương thức cho protocol thì bạn phải cài đặt phương thức đó ngay trong extension.
Protocol Composition
Một đối tượng (class/struct/enum) nào đó cũng đều có khả năng áp dụng một hoặc nhiều protocol cùng lúc. Ví dụ:
Trong ví dụ trên, mình có 02 protocol là Named và Aged. Đồng thời mình xây dựng struct Person, và bạn hãy để ý là struct Person này áp dụng cả 02 protocol Named và Aged cùng lúc. Mỗi một protocol ngăn cách nhau bởi dấu phẩy “,“.
Tính kế thừa
Mình tin rằng đọc tới đây, chắc nhiều bạn sẽ phải thốt lên rằng: “Protocol có thua kém gì class đâu, ngay cả tính kế thừa cũng có nữa mà.” Đúng vậy bạn ạ, một protocol cũng có thể được kế thừa lại từ một hoặc nhiều protocol khác tương tự như class.
➤ Cú pháp:
Bạn thấy không, với cú pháp trên, bạn sử dụng dấu “:” để thực hiện việc kế thừa cho protocol. Cách làm này hoàn toàn tương tự như kế thừa của class. Ngoài ra, bạn cũng có thể chỉ định protocol tạo ra chỉ giành riêng cho class (không cho phép struct/enum thực thi).
➤ Cú pháp:
Các tính chất khác
- Tương tự class, bạn có thể sử dụng toán tử is, as, as? để kiểm tra và ép kiểu protocol.
- Protocol cũng là một kiểu dữ liệu, do đó bạn cũng có thể:
- Khai báo biến, hằng, thuộc tính có kiểu là protocol.
- Dùng protocol là kiểu dữ liệu đầu vào của tham số, kiểu trả ra của hàm đều được.
- Để xem nội dung (cấu trúc) của một protocol nào đó (kể cả protocol hệ thống), bạn sử dụng phím cmd và click chuột trái vào tên protocol đó.
Tổng kết
Đến thời điểm này, mình tin rằng bạn đã có thể bắt tay vào lập trình iOS được rồi. Hoàn thành xong bài học này, mình tạm kết thúc chuỗi bài viết về lập trình Swift cơ bản. Tất nhiên là kiến thức về ngôn ngữ Swift vẫn còn chứ chưa hết đâu bạn nhé. Những bài viết sau bài này về Swift sẽ là những bài viết nâng cao hoặc là những thủ thuật trong lập trình Swift hoặc là những vấn đề lặt vặt khác liên quan tới Swift. Mình hy vọng rằng sẽ tiếp tục được bạn đón nhận, tuy nhiên để đi tiếp thì bạn cần phải hoàn thành các bài học về lập trình Swift cơ bản đã nhé.