訪問(wèn)控制(Access Control)
本文內(nèi)容包括:
- 模塊和源文件
- 訪問(wèn)級(jí)別
- 訪問(wèn)級(jí)別的基本原則
- 默認(rèn)訪問(wèn)級(jí)別
- Single-Target應(yīng)用程序的訪問(wèn)級(jí)別
- Framework的訪問(wèn)級(jí)別
- Unit Test Target的訪問(wèn)級(jí)別
- 訪問(wèn)控制語(yǔ)法
- 自定義類型
- 元組類型
- 函數(shù)類型
- 枚舉類型
- 原始值和關(guān)聯(lián)值
- 嵌套類型
- 子類
- 常量,變量,屬性,下標(biāo)
- getter和setter
- 初始化
- 默認(rèn)初始化方法
- 結(jié)構(gòu)體的默認(rèn)成員初始化方法
- 協(xié)議
- 協(xié)議繼承
- 遵循協(xié)議
- 擴(kuò)展
- 通過(guò)擴(kuò)展遵循協(xié)議
- 泛型
- 類型別名
訪問(wèn)控制(access control) 限定 了 其他源文件或模塊中的代碼 對(duì) 你的代碼的某些部分的訪問(wèn).
這個(gè)特性可以讓你 隱藏代碼的實(shí)現(xiàn)細(xì)節(jié) , 并且可以提供接口(interface)來(lái)訪問(wèn)和使用代碼
你可以 給某個(gè)的類型(類,結(jié)構(gòu)體,枚舉) 以及這些 類型的屬性,方法,構(gòu)造器,下標(biāo)等 設(shè)置 明確的 訪問(wèn)級(jí)別(access level).
協(xié)議 也 可以被 限定在一定的上下文中使用 , 全局常量,變量和函數(shù) 也是如此
Swift 不僅提供了不同的訪問(wèn)級(jí)別 , 而且 通過(guò)為典型的場(chǎng)景提供默認(rèn)的訪問(wèn)級(jí)別的方式 減少了對(duì)于指定明確的訪問(wèn)控制級(jí)別的需求.
事實(shí)上,如果只是開(kāi)發(fā)一個(gè)單一目標(biāo)(single-target)應(yīng)用程序,你可以不用指定明確的訪問(wèn)級(jí)別
注意:
你可以將訪問(wèn)控制應(yīng)用于你的代碼的各個(gè)部分(properties/types/functions等)
并且在下面的章節(jié)中我們會(huì)以 實(shí)體(entity) 代替它們,為簡(jiǎn)單起見(jiàn).
模塊(module)和源文件(source file)
Swift中的 訪問(wèn)控制模型(access control model) 是基于 模塊 和 源文件 這兩個(gè)概念
模塊 是 單個(gè)的代碼分布單元
一個(gè)框架(framework)或一個(gè)應(yīng)用程序(application) 被構(gòu)建和發(fā)布 為 單個(gè)單元(single unit)
并且 **可以被導(dǎo)入另外一個(gè)模塊 **通過(guò)使用Swift關(guān)鍵字 import
在Swift語(yǔ)法中,Xcode的每個(gè) build target , 例如一個(gè)應(yīng)用程序包或框架(app bundle or framework) , 都被視為獨(dú)立的模塊
如果你為了 封裝代碼 和 在多個(gè)應(yīng)用中重用代碼 而 將代碼的各個(gè)部分打包成一個(gè)獨(dú)立的框架 , 那么當(dāng)它被導(dǎo)入到某個(gè)應(yīng)用程序或者其他框架時(shí) , 你在框架中定義的內(nèi)容都將屬于這個(gè)獨(dú)立的模塊
一個(gè)源文件就是一個(gè)模塊中的單個(gè)Swift源代碼文件
(實(shí)際上就是應(yīng)用程序或者框架中的一單個(gè)文件)
盡管我們一般會(huì)將不同的類型分別定義在不同的源文件中
但是單個(gè)源文件也可以包含多個(gè)類型,函數(shù)等的定義
訪問(wèn)級(jí)別(Access Level)
Swift 為 **代碼中的實(shí)體(entity) ** 提供了三種不同的 訪問(wèn)級(jí)別
這些 訪問(wèn)級(jí)別 不僅 與源文件中定義的實(shí)體相關(guān) , 同時(shí) 也與源文件所屬的模塊相關(guān)
public access(公共訪問(wèn))
實(shí)體 可以 在 **定義它的模塊之內(nèi)的任意源文件中 **被使用
實(shí)體 也可以 在 **導(dǎo)入定義它的模塊的任意源文件中 **被使用
當(dāng) 指定一個(gè)框架的公共接口 時(shí) , 你通常使用 public accessinternal access(內(nèi)部訪問(wèn))
實(shí)體 可以 在 **定義它的模塊之內(nèi)的任意源文件中 **被使用
實(shí)體 不可以 在 **定義它的模塊之外的任意源文件中 **被使用
當(dāng) 定義一個(gè)應(yīng)用程序或一個(gè)框架的內(nèi)部結(jié)構(gòu) 時(shí),你通常使用 internal accessprivate access(私有訪問(wèn))
實(shí)體 只能 在 定義它的源文件中 被使用遏暴。
使用 private access 可以 隱藏某些功能的實(shí)現(xiàn)細(xì)節(jié)
public 為最高的(限制最寬松的)訪問(wèn)級(jí)別
private 為最低的(限制最嚴(yán)格的)訪問(wèn)級(jí)別
注意
Swift中的 private access 和大多數(shù)其他語(yǔ)言中的 private access 不同
Swift中的實(shí)體的訪問(wèn)級(jí)別如果被設(shè)置為 private access ,那么實(shí)體的作用范圍是 實(shí)體所在的源文件 ,而不是實(shí)體所在的聲明
這就意味著指黎,一個(gè)類型 可以訪問(wèn) 其所在源文件中的所有private實(shí)體 , 但 定義在其他源文件中 的 該類型的擴(kuò)展 不能訪問(wèn) 該類型的私有成員(private members)
訪問(wèn)級(jí)別基本原則
Swift中的訪問(wèn)級(jí)別遵循一個(gè)總基本原則:
一個(gè)實(shí)體的定義不可以依賴訪問(wèn)級(jí)別更低(限制更為嚴(yán)格)的另一個(gè)實(shí)體
例如:
一個(gè)public變量的定義中不能包含internal或private類型
因?yàn)?internal/private級(jí)別的類型 可能在任何使用該public變量的地方 都不可用一個(gè)函數(shù)的訪問(wèn)級(jí)別不能高于其參數(shù)類型和返回值類型的訪問(wèn)級(jí)別
因?yàn)楹瘮?shù)在被調(diào)用時(shí) 其參數(shù)類型或返回值類型可能會(huì) 不可用于周圍代碼
默認(rèn)訪問(wèn)級(jí)別
大多數(shù)情況下 , 如果你 不為代碼中的實(shí)體顯式指定訪問(wèn)級(jí)別 的話 , 代碼中的實(shí)體 默認(rèn) 為 internal訪問(wèn)級(jí)別
在某些情況下 , 實(shí)體的根據(jù)默認(rèn)環(huán)境所擁有的默認(rèn)訪問(wèn)級(jí)別 與 根據(jù)比較與其相關(guān)的實(shí)體的訪問(wèn)級(jí)別所得出訪問(wèn)級(jí)別 不匹配 時(shí), 需要 顯式指定 訪問(wèn)級(jí)別
單一目標(biāo)(Single-Target)應(yīng)用程序的訪問(wèn)級(jí)別
當(dāng)你 編寫一個(gè)單一目標(biāo)應(yīng)用程序 時(shí)朋凉,你的 應(yīng)用中的代碼通常是自包含在應(yīng)用中 并且 不需要給其他應(yīng)用的模塊使用.
默認(rèn)的internal訪問(wèn)級(jí)別 已經(jīng)滿足了這個(gè)需求,所以我們不需要設(shè)置訪問(wèn)級(jí)別
然而你可以 為了對(duì)模塊中的其他代碼隱瞞一些功能的實(shí)現(xiàn)細(xì)節(jié) 而 標(biāo)記你的一部分代碼為private
框架(Frameworks)的訪問(wèn)級(jí)別
當(dāng)你 開(kāi)發(fā)框架 時(shí),把框架的公開(kāi)接口設(shè)置為public 以便它可以 被其他模塊(例如一個(gè)應(yīng)用導(dǎo)入框架的應(yīng)用) 查看和訪問(wèn).
這個(gè)公開(kāi)的接口 就是 這個(gè)框架的 應(yīng)用程序接口(Application Programming Interface)
注意
你的 框架的任何內(nèi)部實(shí)現(xiàn)細(xì)節(jié) 仍可以使用 默認(rèn)訪問(wèn)級(jí)別internal , 或者 可被標(biāo)記 為 private 如果你想要 對(duì)框架內(nèi)部的其他代碼部分隱藏 的話.
如果你想要 使一個(gè)實(shí)體變成你框架的API的一部分 ,你需要將它 標(biāo)記為public
單元測(cè)試目標(biāo)(Unit Test Targets)的訪問(wèn)級(jí)別
當(dāng)你的 應(yīng)用程序包含Unit Test Target 時(shí),你的 **應(yīng)用程序中的代碼需要被提供給該模塊 ** 以便被測(cè)試.
默認(rèn) 情況下只有標(biāo)記為 public的實(shí)體 才可以 被其他模塊 訪問(wèn)醋安。
然而一個(gè) 單元測(cè)試目標(biāo)(unit test target) 可以 訪問(wèn)任何internal實(shí)體 ,如果你使用 @testable屬性 來(lái)標(biāo)記一個(gè) 產(chǎn)品模塊導(dǎo)入聲明 并將其編譯為具有測(cè)試功能的產(chǎn)品模塊
訪問(wèn)控制語(yǔ)法
通過(guò) 修飾符public,internal,private 來(lái) 定義實(shí)體的訪問(wèn)級(jí)別:
eg.
<pre><code>`
public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}
`</code></pre>
若無(wú)其他規(guī)定,默認(rèn)的訪問(wèn)級(jí)別為internal
這意味著SomeInternalClass和someInternalConstant在不使用修飾符顯式聲明訪問(wèn)級(jí)別的情況下仍然擁有internal訪問(wèn)級(jí)別:
<pre><code>class SomeInternalClass {} //隱式的訪問(wèn)級(jí)別 internal var someInternalConstant = 0 //隱式的訪問(wèn)級(jí)別 internal
</code></pre>
自定義類型
如果想為一個(gè)自定義類型指定訪問(wèn)級(jí)別,在定義類型時(shí)進(jìn)行指定即可
新類型只能在它的訪問(wèn)級(jí)別允許的范圍內(nèi)被訪問(wèn)杂彭。
例如,你定義了一個(gè)private的類,那這個(gè)類就只能在定義它的源文件中可以被用作一個(gè)屬性,函數(shù)參數(shù)或者返回值的類型
類型的訪問(wèn)控制的級(jí)別 也會(huì) 影響到 類型的成員(屬性,方法,構(gòu)造器,下標(biāo))的默認(rèn)訪問(wèn)級(jí)別。
如果 將類型指定為public, 那么 該類型的所有成員的默認(rèn)訪問(wèn)級(jí)別將是internal
(但是可以單獨(dú)設(shè)置某個(gè)成員為internal或private訪問(wèn)級(jí)別)如果 將類型指定為internal(或者不明確指定訪問(wèn)級(jí)別而使用默認(rèn)的internal) ,那么 該類型的所有成員的默認(rèn)訪問(wèn)級(jí)別將是internal
(但是可以單獨(dú)設(shè)置某個(gè)成員為private訪問(wèn)級(jí)別)如果 將類型指定為private ,那么 **該類型的所有成員的默認(rèn)訪問(wèn)級(jí)別也會(huì)變成private **
(也只能是private)
注意
上面提到,一個(gè)public類型的所有成員的訪問(wèn)級(jí)別 默認(rèn)為internal , 而不是public
如果你想 將類型的某個(gè)成員指定為public級(jí)別 ,那么你 必須顯式指定
這樣確保了 該類型的公開(kāi)的API是你選定公開(kāi)的 ,并 避免了將一個(gè)類型的internal內(nèi)容作為公開(kāi)的API來(lái)呈現(xiàn) 的錯(cuò)誤
<pre><code>`
public class SomePublicClass { // 顯式的 public 類
public var somePublicProperty = 0 // 顯式的 public 類成員
var someInternalProperty = 0 // 隱式的 internal 類成員
private func somePrivateMethod() {} // 顯式的 private 類成員
}
class SomeInternalClass { // 隱式的 internal 類
var someInternalProperty = 0 // 隱式的 internal 類成員
private func somePrivateMethod() {} // 顯式的 private 類成員
}
private class SomePrivateClass { // 顯式的 private 類
var somePrivateProperty = 0 // 隱式的 private 類成員
func somePrivateMethod() {} // 隱式的 private 類成員
}
`</code></pre>
元組類型
元組類型的訪問(wèn)級(jí)別 是 元組中使用的多個(gè)類型的訪問(wèn)級(jí)別 中 最嚴(yán)格的那個(gè)訪問(wèn)級(jí)別
例如,如果你構(gòu)建了一個(gè)包含兩種不同類型的元組,其中一個(gè)類型為internal級(jí)別,另一個(gè)類型為private級(jí)別,那么這個(gè)元組的訪問(wèn)級(jí)別為private
注意
元組不像類,結(jié)構(gòu)體,枚舉,函數(shù)那樣有單獨(dú)的定義茬故。
元組的訪問(wèn)級(jí)別在它被使用時(shí)會(huì)被自動(dòng)推斷出來(lái),并且不能被顯式的指定
函數(shù)類型
函數(shù)的訪問(wèn)級(jí)別 是 函數(shù)的參數(shù)類型和返回值類型的訪問(wèn)級(jí)別 中 最嚴(yán)格的那個(gè)訪問(wèn)級(jí)別
如果這種 經(jīng)過(guò)比較得出的訪問(wèn)級(jí)別 與 函數(shù)根據(jù)環(huán)境所擁有的默認(rèn)訪問(wèn)級(jí)別 不匹配,那么就需要 顯式地指定該函數(shù)的訪問(wèn)級(jí)別 作為函數(shù)定義的一部分
下面的例子定義了一個(gè)名為someFunction的全局函數(shù),并且沒(méi)有明確地指定其訪問(wèn)級(jí)別.
也許你會(huì)認(rèn)為該函數(shù)擁有默認(rèn)的訪問(wèn)級(jí)別internal,但事實(shí)并非如此
事實(shí)上,如果按下面這種寫法,代碼將無(wú)法通過(guò)編譯
<pre><code>func someFunction() -> (SomeInternalClass, SomePrivateClass) { // 此處是函數(shù)實(shí)現(xiàn)部分 }
</code></pre>
這個(gè)函數(shù)的返回類型是一個(gè)元組,該元組中包含兩個(gè)自定義的類(在前面定義過(guò)),其中一個(gè)類的訪問(wèn)級(jí)別是internal,另一個(gè)類的訪問(wèn)級(jí)別是private
根據(jù)元組訪問(wèn)級(jí)別的總原則,該元組的訪問(wèn)級(jí)別是private
所以你必須使用private修飾符明確指定該函數(shù)的訪問(wèn)級(jí)別
<pre><code>private func someFunction() -> (SomeInternalClass, SomePrivateClass) { // 此處是函數(shù)實(shí)現(xiàn)部分 }
</code></pre>
將該函數(shù)指定為public或internal,或者使用默認(rèn)的訪問(wèn)級(jí)別internal都是錯(cuò)誤的,因?yàn)槿绻言摵瘮?shù)設(shè)置為public或internal級(jí)別可能會(huì)無(wú)法訪問(wèn)返回值類型-private類盖灸。
枚舉類型
枚舉的成員的訪問(wèn)級(jí)別 和 枚舉類型的訪問(wèn)級(jí)別 相同
你 不能為枚舉成員 指定 不同的訪問(wèn)級(jí)別
如下,枚舉類型CompassPoint被顯式指定為public級(jí)別,它的成員North,South,East,West的訪問(wèn)級(jí)別同樣也是public
<pre><code>public enum CompassPoint { case North case South case East case West }
</code></pre>
原始值(rawValue)和關(guān)聯(lián)值(associatedValue)
枚舉定義中的任何原始值或關(guān)聯(lián)值的類型的訪問(wèn)級(jí)別高于或等于枚舉類型的訪問(wèn)級(jí)別
例如,你不能使用private級(jí)別的類型作為一個(gè)internal訪問(wèn)級(jí)別的枚舉類型的原始值類型
嵌套類型
private類型中定義的嵌套類型自動(dòng)擁有private訪問(wèn)級(jí)別
public或者internal級(jí)別類型中定義的嵌套類型自動(dòng)擁有internal訪問(wèn)級(jí)別
如果想讓public級(jí)別類型中的嵌套類型擁有public訪問(wèn)級(jí)別,那么需要明確指定該嵌套類型的訪問(wèn)級(jí)別為public
子類
你 可以繼承 任何可以在當(dāng)前上下文中被訪問(wèn)的類
子類的訪問(wèn)級(jí)別不得高于父類的訪問(wèn)級(jí)別
例如,你不能編寫一個(gè)父類的訪問(wèn)級(jí)別為internal的public子類
此外,你可以在符合一定的訪問(wèn)級(jí)別的條件下重寫任意可獲得的類成員(方法,屬性,構(gòu)造器,下標(biāo)等)
重寫 可以使 繼承來(lái)的類成員 相比于父類中的版本 更容易被訪問(wèn)
如下所示,類A的訪問(wèn)級(jí)別是public,包含一個(gè)訪問(wèn)級(jí)別為private方法someMethod().類B繼承自類A,訪問(wèn)級(jí)別為internal.
但是在類B中重寫了類A中訪問(wèn)級(jí)別為private的方法someMethod(),并指定為internal級(jí)別(比someMethod()的原是實(shí)現(xiàn)的訪問(wèn)級(jí)別更高)
<pre><code>`
public class A {
private func someMethod() {}
}
internal class B: A {
override internal func someMethod() {}
}
`</code></pre>
只要是在被允許的訪問(wèn)級(jí)別上下文中,一個(gè)比父類成員訪問(wèn)權(quán)限更高的子類成員調(diào)用該父類成員是有效的
<pre><code>`
public class A {
private func someMethod() {}
}
internal class B: A {
override internal func someMethod() {
super.someMethod()
}
}
`</code></pre>
因?yàn)楦割怉和子類B定義在同一源文件中,所以在子類B的someMethod()方法中調(diào)用super.someMethod()是有效的
常量,變量,屬性,下標(biāo)
常量,變量,屬性不能擁有比它們的類型更高的訪問(wèn)級(jí)別磺芭。
例如,定義一個(gè)的public訪問(wèn)級(jí)別的屬性,但是其類型的訪問(wèn)級(jí)別為private是無(wú)效的
同樣,一個(gè)下標(biāo)也不能擁有比它的索引類型或返回值類型更高的訪問(wèn)級(jí)別赁炎。
如果一個(gè)常量,變量,屬性,下標(biāo)的類型是private類型級(jí)別,那么它們也必須被顯式指定指定為private訪問(wèn)級(jí)別
<pre><code>private var privateInstance = SomePrivateClass()
</code></pre>
getter和setter
常量,變量,屬性,下標(biāo)的getter和setter自動(dòng)接收和 它們所屬類型的相同的訪問(wèn)級(jí)別
與getter的訪問(wèn)級(jí)別相比 你可以 給予setter一個(gè)更低的訪問(wèn)級(jí)別
這樣就 可以限定變量,屬性或下標(biāo)的讀寫范圍
你可以通過(guò) 在 var 或 subscript 之前寫 private(set) 或 internal(set) 來(lái)設(shè)置一個(gè)更低的訪問(wèn)級(jí)別
注意
此規(guī)則適用于 存儲(chǔ)型屬性 和 計(jì)算型屬性.
即使你不顯式地指定存儲(chǔ)型屬性的getter和setter,Swift仍然會(huì)隱式地生成getter和setter為你提供用對(duì)該屬性的后備存儲(chǔ)的訪問(wèn).
使用private(set)和internal(set)可以改變這種setter的訪問(wèn)級(jí)別,這對(duì)計(jì)算型屬性的顯式的setter也是如此
如下所示定義了一個(gè)名為TrackedString的結(jié)構(gòu)體,它記錄了一個(gè)字符串屬性被修改的次數(shù)
<pre><code>`
struct TrackedString //隱式的internal結(jié)構(gòu)體
{
private(set) var numberOfEdits = 0
//顯式的private結(jié)構(gòu)體成員的setter和隱式的internal結(jié)構(gòu)體成員的getter
var value: String = "" //隱式的internal結(jié)構(gòu)體成員
{
didSet
{
numberOfEdits += 1
}
}
}
`</code></pre>
TrackedString結(jié)構(gòu)體定義了一個(gè)存儲(chǔ)String值的屬性value,并將初始值設(shè)為""(一個(gè)空字符串).該結(jié)構(gòu)體還定義了另一個(gè)存儲(chǔ)Int值的屬性numberOfEdits,用于記錄屬性value被修改的次數(shù).記錄修改通過(guò)屬性value的didSet觀察器實(shí)現(xiàn),每當(dāng)給 value賦新值時(shí)numberOfEdits的值就會(huì)加一。
結(jié)構(gòu)體TrackedString和屬性value均沒(méi)有顯式指定訪問(wèn)級(jí)別,所以它們都擁有默認(rèn)的訪問(wèn)級(jí)別internal.但是該結(jié)構(gòu)體的numberOfEdits屬性使用了private(set)修飾符,這意味著numberOfEdits屬性只能在定義該結(jié)構(gòu)體的源文件中賦值.
numberOfEdits屬性的getter仍然有默認(rèn)的internal訪問(wèn)級(jí)別,但是他的setter只能用于結(jié)構(gòu)體TrackedString的定義所在的源文件中.這使結(jié)構(gòu)體TrackedString的numberOfEdits屬性只在當(dāng)前的源文件中是可讀寫的,但當(dāng)在同一個(gè)模塊中的其他源文件使用時(shí),將該屬性呈現(xiàn)為只讀屬性.
如果你實(shí)例化TrackedString結(jié)構(gòu)體,并多次對(duì)value屬性的值進(jìn)行修改,你就會(huì)看到numberOfEdits的值會(huì)隨著修改次數(shù)而變化:
<pre><code>var stringToEdit = TrackedString() stringToEdit.value = "This string will be tracked." stringToEdit.value += " This edit will increment numberOfEdits." stringToEdit.value += " So will this one." print("The number of edits is \(stringToEdit.numberOfEdits)") // 打印 “The number of edits is 3”
</pre></code>
雖然你可以在其他的源文件中實(shí)獲取到numberOfEdits屬性的值,但是你不能對(duì)其進(jìn)行賦值.這一限制保護(hù)了該記錄功能的實(shí)現(xiàn)細(xì)節(jié),同時(shí)還提供了方便的訪問(wèn)方式.
注意如果有必要,你可以為getter和setter顯式指定訪問(wèn)級(jí)別.下面的例子將TrackedString結(jié)構(gòu)體明確指定為了public訪問(wèn)級(jí)別.因此結(jié)構(gòu)體的成員擁有默認(rèn)的訪問(wèn)級(jí)別internal.你可以結(jié)合public和private(set)修飾符把結(jié)構(gòu)體中numberOfEdits屬性的getter的訪問(wèn)級(jí)別設(shè)置為public,而setter的訪問(wèn)級(jí)別設(shè)置為private:
<pre><code>public struct TrackedString { public private(set) var numberOfEdits = 0 public var value: String = "" { didSet { numberOfEdits += 1 } } public init() {} }
</code></pre>
構(gòu)造器
自定義構(gòu)造器的訪問(wèn)級(jí)別低于或等于它們初始化的類型的訪問(wèn)級(jí)別
唯一的例外是 必要構(gòu)造器的訪問(wèn)級(jí)別必須和所屬類型的訪問(wèn)級(jí)別相同
如同函數(shù)或方法的參數(shù),構(gòu)造器參數(shù)的訪問(wèn)級(jí)別也不能低于構(gòu)造器本身的訪問(wèn)級(jí)別.
默認(rèn)構(gòu)造器
如同在默認(rèn)構(gòu)造器所述的,Swift會(huì)為結(jié)構(gòu)體和類提供一個(gè)默認(rèn)的無(wú)參數(shù)的構(gòu)造器,只要它們?yōu)樗写鎯?chǔ)型屬性設(shè)置了默認(rèn)初始值,并且未提供自定義的構(gòu)造器.
默認(rèn)構(gòu)造器的訪問(wèn)級(jí)別與所屬類型的訪問(wèn)級(jí)別相同,除非類型的訪問(wèn)級(jí)別是public.
如果一個(gè)類型被指定為public級(jí)別,那么默認(rèn)構(gòu)造器的訪問(wèn)級(jí)別將為internal.
如果你希望一個(gè)public級(jí)別的類型也能在其他模塊中使用這種無(wú)參數(shù)的默認(rèn)構(gòu)造器,你必須提供一個(gè)public訪問(wèn)級(jí)別的無(wú)參數(shù)構(gòu)造器.
結(jié)構(gòu)體默認(rèn)的逐一成員構(gòu)造器
如果結(jié)構(gòu)體中任意存儲(chǔ)型屬性的訪問(wèn)級(jí)別為private,那么該結(jié)構(gòu)體默認(rèn)的成員逐一構(gòu)造器的訪問(wèn)級(jí)別就是private,否則,這種構(gòu)造器的訪問(wèn)級(jí)別是internal.
如同前面提到的默認(rèn)構(gòu)造器,如果你希望一個(gè)public級(jí)別的有默認(rèn)逐一成員構(gòu)造器結(jié)構(gòu)體也能在其他模塊中被使用,你必須自己提供一個(gè)public訪問(wèn)級(jí)別的逐一成員構(gòu)造器.
協(xié)議
如果想 **為一個(gè)協(xié)議類型明確地指定訪問(wèn)級(jí)別 , 在定義協(xié)議時(shí)指定 **即可.
這能使你 創(chuàng)建 只能在特定的代碼環(huán)境中 被遵循的協(xié)議.
(private級(jí)別的protocol,只能被同一源文件中的類型遵循
internal級(jí)別的protocol,只能被同一模塊中的類型遵循
public級(jí)別的protocol,可以被同一模塊中和其他模塊中的類型遵循)
你不能對(duì)協(xié)議中的要求設(shè)置訪問(wèn)級(jí)別(如果設(shè)置了訪問(wèn)級(jí)別標(biāo)識(shí)符,Xcode會(huì)報(bào)錯(cuò):'xxx'modifier cannot be used in protocols,并提示你刪除).
這樣能確保該協(xié)議的所有要求都可以被任意遵循者都實(shí)現(xiàn)
協(xié)議繼承
如果定義了一個(gè)繼承自其他協(xié)議的新協(xié)議,新協(xié)議擁有的訪問(wèn)級(jí)別最高也只能和被繼承協(xié)議的訪問(wèn)級(jí)別相同.
例如,你不能將繼承自internal的協(xié)議的新協(xié)議定義為public的協(xié)議.
遵循協(xié)議
當(dāng)一個(gè)類型能夠遵循的一個(gè)指定訪問(wèn)級(jí)別的協(xié)議時(shí) , 協(xié)議的要求在類型中的實(shí)現(xiàn)的訪問(wèn)級(jí)別 必須高于或等于 該類型的訪問(wèn)級(jí)別 和 該協(xié)議的訪問(wèn)級(jí)別 中 最低的訪問(wèn)級(jí)別 并且 低于或等于 該類型的訪問(wèn)級(jí)別 和 該協(xié)議的訪問(wèn)級(jí)別 中 最高的訪問(wèn)級(jí)別
在類型的定義中實(shí)現(xiàn)協(xié)議的要求時(shí),Xcode會(huì)在要求的名稱前補(bǔ)全相應(yīng)的修飾符為 該類型的訪問(wèn)級(jí)別 和 該協(xié)議的訪問(wèn)級(jí)別 中 最低的訪問(wèn)級(jí)別
注意
Swift和Objective-C一樣,協(xié)議的一致性是全局的,在同一程序中一個(gè)類型不可能用兩種不同的方式遵循同一個(gè)協(xié)議.
擴(kuò)展
你可以在類,結(jié)構(gòu)體,枚舉的訪問(wèn)級(jí)別允許的代碼環(huán)境中對(duì)類,結(jié)構(gòu)體,枚舉進(jìn)行擴(kuò)展.
擴(kuò)展中添加的成員具有和原始類型中的成員默認(rèn)一致的訪問(wèn)級(jí)別.
如果你擴(kuò)展了一個(gè)public或者internal類型,擴(kuò)展中的任何新成員將具有默認(rèn)的internal訪問(wèn)級(jí)別.如果你擴(kuò)展了一個(gè)private類型,擴(kuò)展中任意新成員則擁有默認(rèn)的private訪問(wèn)級(jí)別.
或者,你可以明確標(biāo)記擴(kuò)展的訪問(wèn)級(jí)別(例如,private extension)來(lái)給該擴(kuò)展中的所有成員指定一個(gè)新的默認(rèn)訪問(wèn)級(jí)別.
這個(gè)新的默認(rèn)訪問(wèn)級(jí)別仍然可以在擴(kuò)展中被個(gè)別的類型成員的顯式的訪問(wèn)級(jí)別覆蓋
<pre>
<code>
`
internal extension Int//只為擴(kuò)展中所有新的成員指定默認(rèn)訪問(wèn)級(jí)別internal
{
var valueInString :String//默認(rèn)的internal
{
get
{
return String(self)
}
}
private var doubledValue :Int//用顯式的private覆蓋隱式的internal
{
get
{
return self * 2
}
}
}
`
</code>
</pre>
通過(guò)擴(kuò)展遵循協(xié)議
如果你想通過(guò)擴(kuò)展使某類型遵循協(xié)議,你不能在顯式的為該擴(kuò)展指定訪問(wèn)級(jí)別.(Xcode報(bào)錯(cuò):'xxx' modifier cannot be used with extensions that declare protocol conformances)
在 協(xié)議-遵循協(xié)議 中有描述:
當(dāng)一個(gè)類型能夠遵循的一個(gè)指定訪問(wèn)級(jí)別的協(xié)議時(shí) , 協(xié)議的要求在類型中的實(shí)現(xiàn)的訪問(wèn)級(jí)別 必須高于或等于 該類型的訪問(wèn)級(jí)別 和 該協(xié)議的訪問(wèn)級(jí)別 中 最低的訪問(wèn)級(jí)別 并且 低于或等于 該類型的訪問(wèn)級(jí)別 和 該協(xié)議的訪問(wèn)級(jí)別 中 最高的訪問(wèn)級(jí)別
在類型的定義中實(shí)現(xiàn)協(xié)議的要求時(shí),Xcode會(huì)在要求的名稱前補(bǔ)全相應(yīng)的修飾符為 該類型的訪問(wèn)級(jí)別 和 該協(xié)議的訪問(wèn)級(jí)別 中 最低的訪問(wèn)級(jí)別
因此 當(dāng)某類型想要通過(guò)擴(kuò)展來(lái)遵循協(xié)議時(shí) , 協(xié)議的要求在該類型的此擴(kuò)展中的實(shí)現(xiàn)的訪問(wèn)級(jí)別 也取決于 協(xié)議的訪問(wèn)級(jí)別 , 所以 如果你想通過(guò)擴(kuò)展使某類型遵循協(xié)議,你不能在顯式的為該擴(kuò)展指定訪問(wèn)級(jí)別
泛型
泛型類型或泛型函數(shù)的訪問(wèn)級(jí)別 是 其本身的訪問(wèn)級(jí)別 和 類型參數(shù)的類型約束的訪問(wèn)級(jí)別 中 最低的訪問(wèn)級(jí)別
類型別名
你定義的任何類型別名都會(huì)被當(dāng)作獨(dú)特的類型,以便于進(jìn)行訪問(wèn)控制.
類型別名的訪問(wèn)級(jí)別低于或等于其表示的類型的訪問(wèn)級(jí)別.
例如,private級(jí)別的類型別名可以作為public,internal,private類型的別名,但是public級(jí)別的類型不能作為internal或private類型的別名钾腺。
注意
這條規(guī)則也適用于 為滿足協(xié)議一致性而將類型別名用于關(guān)聯(lián)類型的情況 徙垫。
OVER
我自己都看吐了~