Swift 中的 access control 主要區分兩種環境,分別是 module 跟 source file,
在 Xcode 中,一個 target 或是一個 library 可以識別成一個 module,
source file 指的就是單一的 swift 檔案。
Open && Public
代表權限可以在任何 module 的 source file 使用。
module A
open class MyClassA {
}
module B
class MyClassB {
let c = MyClassA()
}
兩者的差別會出現在使用 classes 的時候,
是使用 public 的 class 無法在其他的 module 繼承,但 open 可以,
class 的 property 或是 function 等等也是相同的情況。
module A
open class MyClassA {
}
public class MyClassA2 {
}
module B
class MyClassB: MyClassA {
}
上述如果繼承 MyClassA2 會出現 error。
Internal
限制只能在所屬的 module 內的 source file 使用。
module A
internal class MyClassA {
}
class AnotherMyClassA {
let c = MyClassA()
}
module B
class MyClassB {
let c = MyClassA()
}
上述的 MyClassB 會有 error。
File-private
限制只能在此 source file 使用。
fileprivate class MyClass {
}
let c = MyClass()
class MyClass2 {
let c = MyClass()
}
上述中的 MyClass2 無法建立 MyClass 型別,因為在不同的檔案內無法使用。
Private
限制在所屬的程式區塊。
class MyClass {
private var num = 123
}
let c = MyClass()
c.num = 456
上述無法操作 num,因為 num 限制在 MyClass 的區塊內使用。
自定義限制權限
決大部分的型別,若不額外設定,在宣告時便會將 internal 當作預設權限,
自訂時,要注意其自定義的型別與其內部成員的關係。
例如,若將一個 class 設定為 fileprivate,那麽內部成員預設就會變成 fileprivate,
且針對內部成員不能設定超過 fileprivate 的權限,也就是只能設定 fileprivate 或 private。
fileprivate class MyClass {
var num = 123
private func myFunc() {
}
}
Tuple
在 tuple 內,如果有兩個不同限制權限的型別,會以最低 level 的當成此 tuple 的限制。
比如說有 internal 與 private,那麼此 tuple 就會是 private。
Function
若 function 的參數或回傳值是有其他的權限,必須對 function 改變限制權限來符合其參數或是回傳值。
class MyClass {
private class MyClass2 {
}
private func() -> MyClass {
}
}
Enumeration
沒辦法對 enumeration 內的 case 單一設定不同的限制權限。
如果是設定初始值,初始值型別的限制權限不能超過 enumeration 本身的權限。
Subclass
Subclass 的權限不能比 sueprclass 還高,但是內部成員在某些情況下是允許的。
public class MyClass {
fileprivate func myFunc() {
}
}
internal class MyClass2: MyClass {
override internal func myFunc() {
super.myFunc()
}
}
上述的例子,MyClass2 的權限並沒有比 MyClass 來的高,
但是 override 的 fuction 權限卻比 superclass 還高,
因為在 MyClass2 內呼叫 super myFunc, 而 MyClass 跟 MyClass2 因為在同一個 source file,
所以是可以正常被呼叫到的,如果 MyClass2 寫在跟 MyClass 不同的 source file 就無法正常執行。
變數,常數,property 與 subscript
這些的限制權限都不能高過於本身的型別。
Getter & Setter
與變數常數相同的規則,比較不同的是,可以額外針對 set 做較嚴格的限制權限。
class MyClass {
private(set) var num = 0
var numP: Int {
didSet {
num = numP
}
}
}
Initializer
Initializer 基本上會跟著所屬的 class 或是 structure 的限制權限而改變,
但如果有在 class 或是 structure 使用 public 或是 open 的話,
都必須對 initializer 宣告 public 才能使用。
Protocol
- Protocol 內宣告的限制權限必定與 protocol 本身相同,無法更改。
- Porotocol 內使用的型別限制權不能比 protocol 本身更低。
- 實作的限制權限會 follow 原本的 protocol。
- 可以修改實作的限制權限,但不能比原本的 protocol 更低。
Extension
建立的任何 extension 都會參照原本的型別限制權限,
也可以讓 extension 有新的限制權限,其內部成員都會跟隨新的限制權限。
使用 extension 實作 protocol 的情況下,不能修改 extension 的限制權限。