1. Khái niệm chung:

Closures là những khối chức năng độc lập có thể dược truyền qua và sử dụng trong code của bạn. Closures trong Swift tương tự như các khối lệnh trong C và Objective-C và tương tự như lambdas trong các ngôn ngữ khác.

Closures co thể nắm bắt và lưu trữ các tham chiếu đến bất kỳ biến và hằng số nào từ phạm vi mà chúng được định nghĩa. Điều này được hiểu là “bao đóng” các biến và hằng số. Swift sẽ xử lý tất cả việc quản lý bộ nhớ của việc nắm bắt cho bạn

  • Chú ý: Đừng lo lắng nếu bạn chưa hình dung ra được kiểu năm bắt. Nó sẽ được giải thích chi tiết trong mục ‘nắm bắt giá trị”

Các hàm toàn cục và các hàm lồng nhau (đã được nhắc tới trong mục “Functions”) thực tế là các trường hợp đặc biết của closure. Closure có 3 dạng:

  • Hàm toàn cục: là các closure có tên và không nắm bắt bất kỳ giá trị nào.
  • Hàm lồng nhau: là các closure có tên và có thể nắm bắt các giá trị trong thân hàm.
  • Biểu thức closure: là các closure không tên được viết trong các cú pháp đơn giản, chúng có thể nắm bắt các giá trị trong phạm vi bao quanh chúng

Các biểu thức closure trong Swift rất gọn gàng, mạch lạc. với sự tối ưu hóa được khuyến khích ngắn gọn, các cú pháp không lộn xọn trong các kịch bản phổ biến. Những tối ưu hóa này bao gồm:

  • Suy ra được các tham số và trả về kiểu dữ liệu từ phạm vi hàm
  • Ẩn các giá trị trả về từ các biểu thức closure đơn
  • Viết nhanh tên dối số
  • Cú pháp Trailling Closure. 

2. Biểu thức closure:

Các hàm lồng nhau là 1 phương tiện hữu ích cho việc đặt tên và định nghĩa cho các khối lệnh độc lập như 1 phần của hàm cha. Tuy nhiên để thuận tiện đôi khi ta sẽ viết các hàm 1 cách ngắn gọn hơn bằng các cấu trúc không có tên và khai báo không đầy đủ. Điều này đặc biệt đúng khi bạn làm việc với các hàm hoặc phương thức lấy các hàm như 1 hoặc nhiều đối số của chúng

Biểu thức closure là cách viết các closure trên 1 dòng một cách ngắn gọn và các cú pháp chính. Biểu thức closure cung cấp nhiều cú pháp tối ưu hóa cho việc viết các closure 1 cách ngắn gọn mà không làm mất đi tính gọn gàng hay mục đích của chúng. Ví dụ về biểu thức closure dưới đây giải thích cho tính tối ưu hóa bằng việc định nghĩa lại ví dụ duy nhất về phương thức sorted(by : ) qua 1 vài bước lặp, mỗi lần biểu thị cùng 1 chức năng theo cách ngắn gọn hơn.

3. Phương thức sắp xếp:

Thư viện chuẩn của Swift cung cấp phương thức “sorted(by : )” phương thức này sắp xếp 1 mảng các giá trị của 1 kiều dữ liệu đã biết dựa trên dữ liệu đầu ra của closure sắp xếp mà bạn cung cấp. Khi nó hoàn thành quá trình sắp xếp, phương thức “sorted(by : )” trả về 1 mảng mới có cùng kiểu dữ liệu và kích thước với mảng cũ và với các phần tử đã dược sắp xếp theo thứ tự đúng. Mảng ban đầu không bị biến đổi bởi phương thức “sorted(by : )”.

Ví dụ về biểu thức closure bên dưới sử dụng phương thức “sorted(by : )” để sắp xếp 1 mảng các giá trị String với thứ tự giảm dần theo bảng chữ cái. Đây là mảng ban đầu chưa sắp xếp:

Phương thức “sorted(by : )” chấp nhận 1 closure chọn 2 đối số có cùng kiểu dữ liệu với mảng, và trả về giá trị “Bool” để kết luận dù giá trị đầu tiên nên xuất hiện trước hay sau giá trị thứ hai trong quá trình sắp xếp. Closure sắp xếp cần trả về “true” nếu giá trị đầu tiên xuất hiện trước giá trị thứ 2, nếu không thì trả về “false”

Ví dụ này sắp xếp 1 mảng các giá trị String vậy nên closure sắp xếp này cần có kiểu trả về của hàm là (String, String) -> Bool

1 cách để thực hiện closure sắp xếp là viết 1 hàm thông thường với form chuẩn, sau đó truyền nó vào như 1 đối số của phương thức “sorted(by : )”

Nếu chuỗi thứ nhất (s1) lớn hơn chuỗi thứ hai (s2) thì hàm “backward(_: _ )”  trả về “true” và chỉ ra rằng s1 phải xuất hiện trước s2 trong dãy đã sắp xếp. Với các ký tự của chuỗi ký tự, “lớn hơn” nghĩa là “xuất hiện sau trong bảng chữ cái”. Có nghĩa là ký tự “B” “lớn hơn” ký tự “A”, và chuỗi ký tự “Tom” lớn hơn chuỗi ký tự “Tim”. Điều này cho ra sự sắp xếp ngược bảng chữ cái với “Barry” bị thay thế bởi “Alex” và cứ tiếp tục như vậy.

Tuy nhiên đây là 1 cách khá dài dòng để viết những gì thực chất là 1 biểu thức đơn (a > b). Trong ví dụ này, sẽ phù hợp hơn khi viết closure sắp xếp trên 1 dòng đó là sử dụng cú pháp biểu thức closure.

4. Cú pháp biểu thức Closure:

Cú pháp biểu thức closure có dạng chung sau:

Tham số trong biểu thức cú pháp closure có thể là tham số dạng in-out nhưng chúng không được có giá trị mặc định. Các tham số dạng variadic cũng có thể được sử dụng nếu bạn đặt tên cho chúng. Các Tuples có thể ddwwocj sử dụng như những tham số và các giá trị trả về

Ví dụ bên dưới cho thấy 1 cách viết khác của hàm “backward(_:_:)” ở trên dưới dạng 1 biểu thức closure

Chú ý rằng việc khai báo các tham số và giá trị trả về trong closure giống với cách khai báo trong hàm “backward(_:_:)”. Cả 2 trường hợp đều viết là ” (s1 : String, s2 : String) -> Bool”. Tuy nhiên trong cách viết của closure, tham số và giá trị trả về được viết gọn lại với nhau chứ không tách biệt khỏi nhau.

Hàm closure bắt đầu bằng từ khóa “in”. từ khóa chỉ ra sự định nghĩa các tham số của closure và kiểu trả về đã hoàn tất và thân hàm closure đang bắt đầu

Bởi vì thân hàm closure rất ngắn nên chúng thường được viết gọn trong 1 dòng:

Điều này minh họa rằng toàn bộ phương thức “sorted(by :)” đã được tái hiện lại như cũ. Cặp dấu ngoặc đơn vẫn bao bọc các đói số của phwong thức. Tuy nhiên các đối số đó nay đã nằm trên cùng 1 dòng.

(Còn nữa)

Link phần 2: https://techmaster.vn/posts/35247/tim-hieu-ve-closure-trong-swift-phan-2

Link phần 3: https://techmaster.vn/posts/35248/tim-hieu-ve-closure-trong-swift-phan-3

Link phần cuối: https://techmaster.vn/posts/35249/tim-hieu-ve-closure-trong-swift-phan-cuoi