Có thể bạn không để ý nhưng khi Swift 4 ra đời thì đã có một sự thay đổi nhỏ nhưng  rất quan trọng ở cơ chế private access level. Và có những sự thay đổi gì ở Access level ở Swift 4? Vai trò của  fileprivate bây giờ là gì? Hãy cùng nhau giải đáp những câu hỏi trên qua bài viết dưới đây.

Giống như Swift 3 thì chúng ta vẫn có 5 mức access level theo thứ tự từ mở -> đóng:

  • open bạn có thể truy cập các  open classes và các class member từ bất kỳ source file nào trong module đang được định nghĩa hoặc từ nơi nào mà import module đó. Bạn cũng có thể subclass một open class hoặc override một open class member bên trong đó.

  • public cũng giống như open nhưng hạn chế viêc subclass và override. Bạn chỉ có thể subclass một public class bên trong cùng một module, tương tự đối với override. Bạn nên lưu ý đến cái này khi muốn viết một framework, để đảm bảo cho framework đó có thể subclass hay override được thì bạn phải để cho nóopen.

  • internal cho phép sử dụng bất kỳ source file nào trong module đó nhưng ở bên ngoài thì không, đây chính là cấp độ truy cập mặc định. 

  • fileprivate là 1 access control giới hạn trong 1 file, thường dùng cho extension.

  • private access control này cho phép sử dụng chỉ trong scope và trong Swift 4 thì nó đã được mở rộng ra cho các extension khai báo trong file đó. 

Trong Swift 3 nếu bạn muốn một extension có quyền truy cập tới một private property hoặc method, bạn phải sử dụng fileprivate

class RootViewController: UIViewController {
  private var started = false
}

Nếu tôi có một extension của một class trong file này, tôi sẽ không thể truy cập vào property started:

extension RootViewController {
  func doSomething {
    if started { ... } // Error - no private access (Swift 3)
  }
}

Khi mà extension dần trở nên phổ biến và được sử dụng nhiều hơn thì cũng dẫn đến việc sử dụng fileprivate cũng tăng dần, khi mà chúng ta cần phân tách việc khai báo các thành phần base và các thành phần customize ra.

// RootViewController.swift
class RootViewController: UIViewController {
  fileprivate var started = false
}

extension RootViewController {
  func doSomething {
    if started { ... } // fileprivate access allowed
  }
}

Và ở Swift 4 thì Apple đã giới hạn fileprivate bằng cách mở rộng phạm vi cho private access gồm cho cả các extension. Do đó đoạn code trên sẽ chạy tốt trên Swift 4.

// RootViewController.swift
class RootViewController: UIViewController {
  private var started = false
}

extension RootViewController {
  func doSomething {
    if started { }     // private access allowed (Swift 4)
  }
}

Lưu ý là extension vẫn phải cùng một source file với private property:

// RootViewController+Extension.swift
extension RootViewController {
  func doExtra {
    if started { }     // no private access from here
  }
}

 

Vậy thì khi nào chúng ta sử dụng fileprivate?. Hãy xem ví dụ sau, giả dụ tôi có một class Widget với một vài private, fileprivate method như sau:

// Widget.swift
class Widget {   
  private func privateMethod() { ... }
  fileprivate func fileprivateMethod() { ... }
}

Mặc dù method nằm ngoài source file nhưng còn trường hợp một subclass nằm trong file thì sao?. Đó không phải là một extension của class  Widget do vậy sẽ không thể truy cập vào private method, nhưng fileprivate method thì có thể.

// Widget.swift
class SpecialWidget: Widget {
  func start() {
//  privateMethod()      // No access to private method
    fileprivateMethod()  // fileprivate access allowed
  }
}