Chắc là trong các ngôn ngữ khác, các bạn đều biết tầm quan trọng của lập trình hướng đối tượng. Vậy thì lập trình hướng đối tượng trong Swift sẽ được thực hiện như thế nào? Đó chính là nội dung của bài viết này, hôm nay mình sẽ hướng dẫn bạn cách thức khai báo và sử dụng class trong Swift.
Khai báo class
Trước tiên, mình nhắc khái niệm một xíu nhé. Bạn nào đã biết thì cũng nên xem qua, biết đâu thu hoạch được thêm điều gì đó thì sao.
Class là gì?
Có 02 ý mình muốn nhắc lại một xíu về class:
- Lớp (class) có thể được hiểu là khuôn mẫu để tạo ra các đối tượng. Trong một lớp, các biến sẽ mô tả các thuộc tính và các hàm sẽ mô tả các phương thức. Khi đã định nghĩa được lớp, bạn có thể tạo ra các đối tượng từ lớp này. Lớp thường hay được sử dụng như một kiểu dữ liệu để tạo ra các đối tượng.
- Trong Swift, một lớp thường được định nghĩa trong một tập tin duy nhất. Chỗ này khác với Objective C bạn nhé, đối với Objective C thì bạn cần 02 tập tin (interface và implementation).
Khai báo class
Cú pháp khai báo class khá giống với struct, bạn khai báo như sau:
➤ Ví dụ: Vận dụng cú pháp trên, mình xây dựng class Rectangle như sau.
Từ ví dụ trên, bạn có thể thấy rằng việc khai báo thuộc tính của một class tương tự như cú pháp khai báo biến thông thường. Các thuộc tính cũng được thiết lập giá trị măc định ngay khi khai báo.
Các loại thuộc tính của class
Về cơ bản, việc khai báo thuộc tính của class trong Swift cũng tương tự các ngôn ngữ khác. Tuy nhiên có một số thuộc tính có tính chất khá đặc biệt, phần này mình sẽ tập trung vào những thuộc tính như vậy nhé.
set và get
Khối lệnh set / get qui định cách thức xử lý dữ liệu đầu vào (gán giá trị) và đầu ra (trả giá trị) của một thuộc tính.
➤ Ví dụ: Bạn tiếp tục sử dụng class Rectangle ở trên nhé. Trong ví dụ này mình sẽ bổ sung thêm thuộc tính area với khối lệnh set / get như sau:
➤ Lưu ý: Bạn có thể bỏ khuyết set để tạo thuộc tính read-only nhưng không được khuyết get. Ngoài ra, bạn cũng có thể tận dụng khối lệnh set để kiểm tra tính hợp lệ của giá trị được gán vào. Đây là những đặc điểm khá hay của khối lệnh set / get mà bạn nên tận dụng.
willSet và didSet
Bên cạnh set / get, swift còn hỗ trợ khối lệnh willSet và didSet để theo dõi sự thay đổi của thuộc tính.
- willSet : được thực thi trước khi giá trị được gán.
- didSet : được thực thi sau khi đã gán giá trị.
➤ Ví dụ: Mình vẫn sử dụng class Rectangle, nhưng lần này mình sửa thuộc tính width một xíu nhé.
Khối lệnh willSet trong ví dụ trên sẽ kiểm tra giá trị “chuẩn bị” được gán vào biến width. Nếu không hợp lệ (nhỏ hơn 0) thì thông báo lỗi. Bạn hãy lưu ý trong trường hợp giá trị không hợp lệ, khối lệnh willSet sẽ không ngăn lại việc gán giá trị đâu nhé. Giá trị vẫn sẽ được gán vào thuộc tính, tuỳ mục đích mà bạn sử dụng khối lệnh này theo ý muốn của bạn.
Thuộc tính lazy
Thuộc tính lazy được dùng cho những thuộc tính không thể xác định trước giá trị cho đến khi thuộc tính được khởi tạo (hay cho đến khi chúng ta gọi đến thuộc tính đó).
- Đây là một kĩ thuật để trì hoãn việc tạo ra một đối tượng cho đến khi thực sự gọi đến nó.
- Điều này rất hữu ích để tránh lãng phí bộ nhớ.
➤ Lưu ý: Thuộc tính lazy phải ở dạng biến (var), mà không được là hằng (let) bởi đặc điểm của hằng là phải có giá trị trước khi khởi tạo. Thông thường, khi khai báo thuộc tính lazy thì thuộc tính này sẽ được gán với một hàm hoặc closure nào đó. Việc khai báo thuộc tính lazy khá đơn giản, cú pháp như sau:
➤ Ví dụ: Sử dụng lại class Rectangle, mình sẽ điều chỉnh lại thuộc tính area là thuộc tính lazy như sau:
Thuộc tính area không cần xác định trước giá trị do không biết trước được diện tích hình chữ nhật là bao nhiêu. Mà giá trị của thuộc tính này sẽ được tự tính dựa vào giá trị width và height sau khi hình chữ nhật được khởi tạo. Cách thức sử dụng cũng giống như các thuộc tính khác, ví dụ:
Các dạng phương thức (hàm) trong Swift
Phương thúc khởi tạo
Trong Swift có 02 dạng phương thức tạo phổ biến:
Designated Initializer
Đây là hàm khởi tạo thông thường tương tự như các ngôn ngữ lập trình khác. Hàm khởi tạo này thường được sử dụng để gán giá trị ban đầu cho toàn bộ các thuộc tính lưu trữ (không bắt buộc cho thuộc tính optional).
➤ Cú pháp:
➤ Lưu ý: Chỉ nên sử dụng designated initializer để khởi gán giá trị cho các thuộc tính cần thiết. Ngoài ra bạn không nên gọi hàm khởi tạo init nào khác bên trong thân của nó.
Convenience Initializer
Đây là dạng hàm khởi tạo mà bên trong hàm này, bạn có thể gọi đến một hàm khởi tạo init khác của chính class này. Hàm khởi tạo này sẽ giúp bạn khắc phục hạn chế của designated initializer.
➤ Cú pháp:
➤ Lưu ý: convenience initializer chỉ cho phép tạo các biến/hằng tính toán và gọi thực thi một hàm init khác của class này. Ngoài ra hàm này không cho phép bạn dùng self để gán giá trị cho các thuộc tính con trong class.
➤ Ví dụ: Mình sẽ xây dựng ví dụ cho cả 02 loại hàm designated và convenience initializer luôn nhé.
Ví dụ trên mình đã chú thích đầy đủ, chắc là bạn có thể hiểu được 02 loại hàm designated và convenience initializer rồi đúng không. Tóm lại designated và convenience initializer đều có những đặc điểm riêng của mình. Tuỳ theo từng tình huống cụ thể mà bạn sử dụng cho phù hợp. Ngoài ra trong Swift, còn hàm khởi tạo required init nữa nhưng tạm thời mình sẽ không trình bày. Phần này mình sẽ để sang bài viết về Protocol thì sẽ trình bày sau nhé.
Phương thức huỷ
Phương thức huỷ được sử dụng trong những trường hợp bạn cần “dọn dẹp” dữ liệu cho class. Thực tế thì bản thân mình cũng không hay sử dụng lắm, ngoại trừ những trường hợp đặc biệt mà thôi bởi Swift có cơ chế dọn dẹp rất tốt rồi.
➤ Cú pháp:
Phương thức xử lý
Phương thức xử lý là các phương thức được dùng để xây dựng các hành vi cho class. Hiểu cách khác thì đây chính là các hàm chức năng của class mà bạn đang xây dựng. Cú pháp khai báo phương thức xử lý tương tự như việc khai báo hàm / thủ tục thông thường, do đó mình không xây dựng cú pháp nữa nhé.
➤ Ví dụ: Mình sẽ minh hoạ bằng ví dụ cụ thể luôn nhé. Trong ví dụ này mình sẽ sử dụng lại class Rectangle, như sau:
Khởi tạo đối tượng và truy xuất
Việc sử dụng class để tạo các đối tượng tương đối dễ dàng và tương tự các ngôn ngữ khác. Ví dụ:
Khá đơn giản phải không bạn. Sau khi tạo được đối tương rồi thì việc truy xuất các thành phần con bên trong cũng khá dễ dàng. Bạn sử dụng dấu “.” để truy xuất thành phần con bên trong.
- Truy xuất thuộc tính:
- Truy xuất phương thức:
Tổng kết
Mình đã trình bày các kiến thức cơ bản của lập trình hướng đối tượng qua việc sử dụng class. Bài viết này giành cho những bạn nào đã biết về lập trình hướng đối tượng qua các ngôn ngữ khác (C#, Java, …). Nếu bạn là người mới học lập trình thì có thể sẽ khó hiểu hết các nội dung này. Trong trường hợp này bạn nên tìm đọc các bài viết về lập trình hướng đối tượng đã nhé.