此篇將介紹前綴詞 open、public、private...等所代表的意義。Swift 提供存取控制 (access control) 的特性,可以為程式碼或模組設定存取的權限,決定哪些部分可以開放給外部的程式碼所使用,決定要隱藏的部分,如此一來,可以避免提供給外部使用時可以輕易修改內部程式碼所造成的混亂。
Swift 存取控制模型,基於模組 (model) 和 源檔案 (source file) 的概念上。
Module: 一個模組可代表一個 bundle ID 下的應用程式,或指一個 framework。因此在一個應用程式中,輸入了很多 framework,每一個 framework 內即一個 module。
Source Files: 就是指每一個 *.swift 檔案。
Swift 提供了五種不同的存取級別:
Open 存取: 擁有最高的存取權限,即最少的限制,可被同一個 module 的任何檔案存取,或一個不同的 module 存取。
public 存取: 可被同一個 module 的任何檔案存取,或一個不同的 model 存取。Classes 擁有 public 存取或更多限制的存取層級,只能在其定義的 module 為 subclasses。Classes 的成員擁有 public 存取或更多限制存取層級,只能在其定義的 module 的 subclasses 覆載。
Internal 存取: 可被其定義的 module 內的任何 sourcr file 所存取,但無法被外部 module 的任何檔案存取。當定義一個應用程式或 framework 的內部結構時,通常使用 internal 存取。
File-private 存取: 存取限制為其自定義的 source file。當在整份文件中使用這些詳細內容時,使用 file-private 存取來隱藏特定功能的實現細節。
Private 存取: 最低存取權限,即最多限制。宣告區塊和同一份檔案的擴展宣告才可存取。
利用在實體宣告的開頭放置 open
、public
、internal
、fileprivate
或 private
修飾符之一來定義實體的存取級別。
public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
fileprivate func someFilePrivateFunction() {}
private func somePrivateFunction() {}
除非另有說明,否則預設存取級別為 internal
,意思是 SomeInternalClass 和 someInternalConstant 可以在沒有顯式存取級別修飾符的情況下編寫,並且仍然具有 internal
存取級別:
class SomeInternalClass {} // implicitly internal
let someInternalConstant = 0 // implicitly internal
如果要為自定義型別指定顯式訪問級別,請在定義類型時執行此操作。然後,只要存取級別允許,就可以使用新型別。例如,如果定義了文件專用類 (file-private class),則該類只能在定義了文件專用類的源文件中用為屬性的型別,或用作函數參數或返回型別。
型別的存取控制級別也會影響該型別的成員(屬性、方法、初始化程序和下標)的預設存取級別。如果將型別的存取級別定義為私有或文件私有,則其成員的預設存取級別也將為私有或文件私有。如果將惜別的存取級別定義為內部存取或公共存取(或使用內部訪問的默認訪問級別,而未明確指定訪問級別),則該型別成員的預設存取級別將是內部存取。
重要: 公用型別預設為具有內部成員,而不是公用成員。如果要讓型別成員公開,則必須明確地將其標記為公共成員。此要求確保可以選擇發布型別的面向公眾的 API,並避免錯誤地將型別的內部工作方式呈現為公共 API。
public class SomePublicClass { // explicitly public class
public var somePublicProperty = 0 // explicitly public class member
var someInternalProperty = 0 // implicitly internal class member
fileprivate func someFilePrivateMethod() {} // explicitly file-private class member
private func somePrivateMethod() {} // explicitly private class member
}
class SomeInternalClass { // implicitly internal class
var someInternalProperty = 0 // implicitly internal class member
fileprivate func someFilePrivateMethod() {} // explicitly file-private class member
private func somePrivateMethod() {} // explicitly private class member
}
fileprivate class SomeFilePrivateClass { // explicitly file-private class
func someFilePrivateMethod() {} // implicitly file-private class member
private func somePrivateMethod() {} // explicitly private class member
}
private class SomePrivateClass { // explicitly private class
func somePrivateMethod() {} // implicitly private class member
}