Swift語(yǔ)法2.24(訪問(wèn)控制)

訪問(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 access

  • internal access(內(nèi)部訪問(wèn))
    實(shí)體 可以 在 **定義它的模塊之內(nèi)的任意源文件中 **被使用
    實(shí)體 不可以 在 **定義它的模塊之外的任意源文件中 **被使用
    當(dāng) 定義一個(gè)應(yīng)用程序或一個(gè)框架的內(nèi)部結(jié)構(gòu) 時(shí),你通常使用 internal access

  • private 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ò) 在 varsubscript 之前寫 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
我自己都看吐了~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市放棒,隨后出現(xiàn)的幾起案子姻报,更是在濱河造成了極大的恐慌,老刑警劉巖间螟,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吴旋,死亡現(xiàn)場(chǎng)離奇詭異损肛,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)荣瑟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門治拿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人笆焰,你說(shuō)我怎么就攤上這事劫谅。” “怎么了嚷掠?”我有些...
    開(kāi)封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵捏检,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我不皆,道長(zhǎng)贯城,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任粟焊,我火速辦了婚禮冤狡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘项棠。我一直安慰自己悲雳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布香追。 她就那樣靜靜地躺著合瓢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪透典。 梳的紋絲不亂的頭發(fā)上晴楔,一...
    開(kāi)封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音峭咒,去河邊找鬼税弃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛凑队,可吹牛的內(nèi)容都是我干的则果。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼漩氨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼西壮!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起叫惊,我...
    開(kāi)封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤款青,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后霍狰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體抡草,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡饰及,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了渠牲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旋炒。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖签杈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鼎兽,我是刑警寧澤答姥,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站谚咬,受9級(jí)特大地震影響鹦付,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜择卦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一敲长、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧秉继,春花似錦祈噪、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至杠茬,卻和暖如春月褥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瓢喉。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工宁赤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人栓票。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓决左,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逗载。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哆窿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 本章將會(huì)介紹 模塊和源文件訪問(wèn)級(jí)別訪問(wèn)控制語(yǔ)法自定義類型子類常量挚躯、變量、屬性擦秽、下標(biāo)構(gòu)造器協(xié)議擴(kuò)展泛型類型別名位運(yùn)算...
    寒橋閱讀 884評(píng)論 0 2
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理码荔,服務(wù)發(fā)現(xiàn)漩勤,斷路器,智...
    卡卡羅2017閱讀 134,659評(píng)論 18 139
  • 蘋果在發(fā)布了Xcode 6 Bate 4后為Swift添加了新的特性--訪問(wèn)控制(Access Control)缩搅,...
    DevTalking閱讀 1,670評(píng)論 3 6
  • 我家東邊是一條路 越败,南北走向,路兩邊是兩行白楊樹(shù)硼瓣,形成了一個(gè)“小樹(shù)林”究飞,這片百十米長(zhǎng)的小樹(shù)林,卻給我留下了很多美好...
    酒言醉語(yǔ)閱讀 1,152評(píng)論 39 14
  • 萬(wàn)里山河迎金秋 千家欣喜糧滿倉(cāng) 百舸競(jìng)流浪淘沙 十載光陰隙中度 一輪皓月寄相思 孤枕難眠獨(dú)一身 膝跪佛前合十拜 福...
    A貓與故巷閱讀 210評(píng)論 9 4