當Swift首次引入訪問級別時,對此進行了一些混淆和不解。雖然開發人員對於添加對Swift編程語言的訪問控制感到興奮,但是private
關鍵字的行爲與其他編程語言的行爲不同。
這在Swift 3中已經發生了改變,通過添加另一個關鍵字進行私有訪問控制fileprivate
。區別是微妙但容易理解。
Swift 3 之前
在引入Swift 3之前,private關鍵字將實體(類,結構,枚舉,...)的使用限制在定義它們的源文件中。看下面的例子。
import UIKit
class NotesViewController: UIViewController {
private var dataSource = [String]()
}
extension NotesViewController: UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
...
}
我們聲明一個UIViewController
子類NotesViewController
, 他帶有一個[String]
類型的私有屬性dataSource
。在同一個源文件中,我們爲NotesViewController
類創建一個擴展,遵守UITableViewDataSource
協議。有趣的是我們可以訪問擴展中的dataSource
屬性(dataSource.count
),即使屬性被聲明爲private
。
Swift3中
如果我們將上述代碼片段移植到Swift 3
,編譯器會拋出一個錯誤。它告訴我們dataSource
屬性是一個未解析的標識符。換句話說,通過將dataSource
屬性聲明爲private
,擴展名中不可訪問。
兩個不同的Private:Private 和 filePrivate
Private
您仍然可以使用私人關鍵字進行訪問控制。 Swift團隊已經聽取了社羣的反饋意見,因此,私人關鍵字的含義現在與許多其他編程語言相似。聲明爲私有的實體只能在其聲明的範圍內被訪問。
import UIKit
class NotesViewController: UIViewController {
private var dataSource = [String]()
}
extension NotesViewController: UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
...
}
filePrivate
Swift 3引入了fileprivate關鍵字來替換原來的private關鍵字。您可以試着將dataSource屬性的訪問權限標記爲fileprivate。
import UIKit
class NotesViewController: UIViewController {
fileprivate var dataSource = [String]()
}
extension NotesViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
...
}
顧名思義,fileprivate
關鍵字將對實體的訪問權限於它聲明的源文件。我們可以通過將NotesViewController
類的擴展名移動到單獨的文件來驗證這一點。這導致我們之前遇到的錯誤。
這樣修改的好處
private
和filePrivate
剛開始可能會令人困惑,但是private
擁有更清晰、更直觀的語意。private
的原始實現使許多開發人員,特別是來自其他編程語言的開發人員感到困惑。通過將private
重命名爲fileprivate
,不再如此。該名稱清楚地表示一個實體對於特定(源)文件是私有的,而現在的private
和其他的編程語言裏的private
有相同的語意,更加清晰。