Swift中包含三種權(quán)限控制
- public (公開, 供外部調(diào)用)
- internal (默認(rèn), 限module內(nèi)使用)
- private (私有, 限source file內(nèi)使用)
名詞解釋
- module是個(gè)代碼發(fā)布單元(如Framework或者應(yīng)用程序), 通過使用import關(guān)鍵字導(dǎo)入使用
- A source files是module中的一個(gè)swift文件 (實(shí)際情況就是一個(gè)app或者framework中的一個(gè)swift文件)
internal
默認(rèn)控制權(quán)限, 如果單target用戶,不需要刻意強(qiáng)調(diào)控制權(quán)限,默認(rèn)權(quán)限就足夠了
public
使用場景framework, 用于公開api調(diào)用, 其他framework內(nèi)部使用方法采用 internal 方便framework內(nèi)部調(diào)用,但是對framework外部不可使用
private
原文為(use in sourcefile), 即定義的private僅能在當(dāng)前文件使用,子類及繼承均不能使用
使用等級
private < internal < public
測試訪問控制
@testable 使得internal的也可以被訪問
使用規(guī)則
不能包含比自己使用等級更大的實(shí)體
Demo
新建一個(gè)workspace, 包括一個(gè)framework(CECModuleFrame)和一個(gè)demo(ModuleDemo)
在framework中新建類 ModuleApi.swift
<pre>
`
import Foundation
class ModuleApi {
public func helloWorld() { //警告:Declaring a public instance method for an internal class,表明不能在一個(gè)internal權(quán)限的類中新建一個(gè)public的方法
print("Hello world")
}
}
</pre> 如上代碼所示, 如果不寫控制權(quán)限關(guān)鍵詞,則默認(rèn)為*internal*, 為了讓文件被外部訪問,需要添加public關(guān)鍵詞,如下所示 <pre>
public class ModuleApi {
public init() {
}
// 想被外部訪問,則必須添加public關(guān)鍵詞
public let somePublicProperty = "Module"
// 想被外部訪問,則必須添加public關(guān)鍵詞
public func helloWorld() {
print("Hello world")
}
}
// 外部使用方法:
let api = ModuleApi()
api.helloWorld() // 輸出: Hello world
print(api.somePublicProperty) // 輸出Module
`
</pre>
TupleType訪問權(quán)限
多個(gè)對象,返回最小權(quán)限類型
<pre>(public, internal) 得到的是internal權(quán)限 (public, private) 得到的是private權(quán)限
</pre>
方法訪問控制
<pre>`
public class ModuleApi {
public init() {
}
// 提示出錯(cuò):Method must be declared private because its result uses a private type
func someFunction()->(PrivateClass, InternalClass) {
}
}
private class PrivateClass {
}
internal class InternalClass {
}
`</pre>
Enum類型
選項(xiàng)的權(quán)限跟著enum的定義
<pre>public enum CompassPoint { case North // 訪問權(quán)限為public }
</pre>
類\常量\變量\屬性等都遵循著使用規(guī)則
Getter & Setter
在var 或者subscript前使用private(set) or internal(set)獲得更低的使用權(quán)限
<pre>`
struct TrackedString {
private(set) var numberOfEdits = 0
var value: String = "" {
didSet {
numberOfEdits++
}
}
}
// 可以聯(lián)合使用public和private(set)
public struct TrackedString {
public private(set) var numberOfEdits = 0
public var value: String = "" {
didSet {
numberOfEdits++
}
}
public init() {}
}
`</pre>
Initializers
- A required initializer must have the same access level as the class it belongs to.”
- As with function and method parameters, the types of an initializer’s parameters cannot be more private than the initializer’s own access level.
Default Initializers
As described in Default Initializers, Swift automatically provides a default initializer without any arguments for any structure or base class that provides default values for all of its properties and does not provide at least one initializer itself.
A default initializer has the same access level as the type it initializes, unless that type is defined as public. For a type that is defined as public, the default initializer is considered internal. If you want a public type to be initializable with a no-argument initializer when used in another module, you must explicitly provide a public no-argument initializer yourself as part of the type’s definition.
類或者Struct如果使用了public,默認(rèn)初始器是internal的,所以需要提供一個(gè)對應(yīng)的public的初始器