訪問控制可以限定其它源文件或模塊中的代碼對你的代碼的訪問級別姻采。這個(gè)特性可以讓我們隱藏代碼的一些實(shí)現(xiàn)細(xì)節(jié)劣纲,并且可以為其他人可以訪問和使用的代碼提供接口委刘。
你可以明確地給單個(gè)類型(類、結(jié)構(gòu)體人弓、枚舉)設(shè)置訪問級別沼死,也可以給這些類型的屬性、方法崔赌、構(gòu)造器意蛀、下標(biāo)等設(shè)置訪問級別。協(xié)議也可以被限定在一定的范圍內(nèi)使用健芭,包括協(xié)議里的全局常量县钥、變量和函數(shù)
Swift 不僅提供了多種不同的訪問級別,還為某些典型場景提供了默認(rèn)的訪問級別慈迈,這樣就不需要我們在每段代碼中都申明顯式訪問級別若贮。其實(shí),如果只是開發(fā)一個(gè)單一 target 的應(yīng)用程序痒留,我們完全可以不用顯式聲明代碼的訪問級別谴麦。
注意
為了簡單起見,對于代碼中可以設(shè)置訪問級別的特性(屬性伸头、基本類型匾效、函數(shù)等),在下面的章節(jié)中我們會(huì)稱之為“實(shí)體”熊锭。
模塊和源文件
Swift 中的訪問控制模型基于模塊和源文件這兩個(gè)概念弧轧。
模塊指的是獨(dú)立的代碼單元雪侥,框架或應(yīng)用程序會(huì)作為一個(gè)獨(dú)立的模塊來構(gòu)建和發(fā)布碗殷。在 Swift 中,一個(gè)模塊可以使用 import 關(guān)鍵字導(dǎo)入另外一個(gè)模塊速缨。
在 Swift 中锌妻,Xcode 的每個(gè) target(例如框架或應(yīng)用程序)都被當(dāng)作獨(dú)立的模塊處理。如果你是為了實(shí)現(xiàn)某個(gè)通用的功能旬牲,或者是為了封裝一些常用方法而將代碼打包成獨(dú)立的框架仿粹,這個(gè)框架就是 Swift 中的一個(gè)模塊。當(dāng)它被導(dǎo)入到某個(gè)應(yīng)用程序或者其他框架時(shí)原茅,框架內(nèi)容都將屬于這個(gè)獨(dú)立的模塊吭历。
源文件就是 Swift 中的源代碼文件,它通常屬于一個(gè)模塊擂橘,即一個(gè)應(yīng)用程序或者框架晌区。盡管我們一般會(huì)將不同的類型分別定義在不同的源文件中,但是同一個(gè)源文件也可以包含多個(gè)類型、函數(shù)之類的定義朗若。
訪問級別
Swift 為代碼中的實(shí)體提供了五種不同的訪問級別恼五。這些訪問級別不僅與源文件中定義的實(shí)體相關(guān),同時(shí)也與源文件所屬的模塊相關(guān)哭懈。
- Open 和 Public 級別可以讓實(shí)體被同一模塊源文件中的所有實(shí)體訪問灾馒,在模塊外也可以通過導(dǎo)入該模塊來訪問源文件里的所有實(shí)體。通常情況下遣总,你會(huì)使用 Open 或 Public 級別來指定框架的外部接口睬罗。Open 和 Public 的區(qū)別在后面會(huì)提到。
- Internal 級別讓實(shí)體被同一模塊源文件中的任何實(shí)體訪問彤避,但是不能被模塊外的實(shí)體訪問傅物。通常情況下,如果某個(gè)接口只在應(yīng)用程序或框架內(nèi)部使用琉预,就可以將其設(shè)置為 Internal 級別董饰。
- File-private 限制實(shí)體只能在其定義的文件內(nèi)部訪問。如果功能的部分細(xì)節(jié)只需要在文件內(nèi)使用時(shí)圆米,可以使用 File-private 來將其隱藏卒暂。
- Private 限制實(shí)體只能在其定義的作用域,以及同一文件內(nèi)的 extension 訪問娄帖。如果功能的部分細(xì)節(jié)只需要在當(dāng)前作用域內(nèi)使用時(shí)也祠,可以使用 Private 來將其隱藏。
Open 為最高訪問級別(限制最少)近速,Private 為最低訪問級別(限制最多)诈嘿。
Open 只能作用于類和類的成員,它和 Public 的區(qū)別如下:
- Public 或者其它更嚴(yán)訪問級別的類削葱,只能在其定義的模塊內(nèi)部被繼承奖亚。
- Public 或者其它更嚴(yán)訪問級別的類成員,只能在其定義的模塊內(nèi)部的子類中重寫析砸。
- Open 的類昔字,可以在其定義的模塊中被繼承,也可以在引用它的模塊中被繼承首繁。
- Open 的類成員作郭,可以在其定義的模塊中子類中重寫,也可以在引用它的模塊中的子類重寫弦疮。
把一個(gè)類標(biāo)記為 open夹攒,明確的表示你已經(jīng)充分考慮過外部模塊使用此類作為父類的影響,并且設(shè)計(jì)好了你的類的代碼了胁塞。
訪問級別基本原則
Swift 中的訪問級別遵循一個(gè)基本原則:不可以在某個(gè)實(shí)體中定義訪問級別更低(更嚴(yán)格)的實(shí)體咏尝。
例如:
- 一個(gè) Public 的變量堂湖,其類型的訪問級別不能是 Internal,F(xiàn)ile-private 或是 Private状土。因?yàn)闊o法保證變量的類型在使用變量的地方也具有訪問權(quán)限无蜂。
- 函數(shù)的訪問級別不能高于它的參數(shù)類型和返回類型的訪問級別。因?yàn)檫@樣就會(huì)出現(xiàn)函數(shù)可以在任何地方被訪問蒙谓,但是它的參數(shù)類型和返回類型卻不可以的情況斥季。
默認(rèn)訪問級別
如果你沒有為代碼中的實(shí)體顯式指定訪問級別,那么它們默認(rèn)為 internal 級別(有一些例外情況累驮,稍后會(huì)進(jìn)行說明)酣倾。因此,在大多數(shù)情況下谤专,我們不需要顯式指定實(shí)體的訪問級別躁锡。
單 target 應(yīng)用程序的訪問級別
當(dāng)你編寫一個(gè)單目標(biāo)應(yīng)用程序時(shí),應(yīng)用的所有功能都是為該應(yīng)用服務(wù)置侍,而不需要提供給其他應(yīng)用或者模塊使用映之,所以我們不需要明確設(shè)置訪問級別,使用默認(rèn)的訪問級別 Internal 即可蜡坊。但是杠输,你也可以使用 fileprivate 訪問或 private 訪問級別,用于隱藏一些功能的實(shí)現(xiàn)細(xì)節(jié)秕衙。
框架的訪問級別
當(dāng)你開發(fā)框架時(shí)蠢甲,就需要把一些對外的接口定義為 Open 或 Public,以便使用者導(dǎo)入該框架后可以正常使用其功能据忘。這些被你定義為對外的接口鹦牛,就是這個(gè)框架的 API。
注意
框架依然會(huì)使用默認(rèn)的 internal 勇吊,也可以指定為 fileprivate 訪問或者 private 訪問級別曼追。當(dāng)你想把某個(gè)實(shí)體作為框架的 API 的時(shí)候,需顯式為其指定開放訪問或公開訪問級別萧福。
單元測試 target 的訪問級別
當(dāng)你的應(yīng)用程序包含單元測試 target 時(shí)拉鹃,為了測試辈赋,測試模塊需要訪問應(yīng)用程序模塊中的代碼鲫忍。默認(rèn)情況下只有 open 或 public 級別的實(shí)體才可以被其他模塊訪問。然而钥屈,如果在導(dǎo)入應(yīng)用程序模塊的語句前使用 @testable 特性悟民,然后在允許測試的編譯設(shè)置(Build Options -> Enable Testability)下編譯這個(gè)應(yīng)用程序模塊,單元測試目標(biāo)就可以訪問應(yīng)用程序模塊中所有內(nèi)部級別的實(shí)體篷就。
訪問控制語法
通過修飾符 open射亏,public,internal,fileprivate智润,private 來聲明實(shí)體的訪問級別:
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() {}
除非專門指定及舍,否則實(shí)體默認(rèn)的訪問級別為 internal,這意味著在不使用修飾符顯式聲明訪問級別的情況下窟绷,SomeInternalClass 和 someInternalConstant 仍然擁有隱式的 internal:
class SomeInternalClass {} // 隱式 internal
var someInternalConstant = 0 // 隱式 internal
自定義類型
如果想為一個(gè)自定義類型指定訪問級別锯玛,在定義類型時(shí)進(jìn)行指定即可。新類型只能在它的訪問級別限制范圍內(nèi)使用兼蜈。例如攘残,你定義了一個(gè) fileprivate 級別的類,那這個(gè)類就只能在定義它的源文件中使用为狸,可以作為屬性類型歼郭、函數(shù)參數(shù)類型或者返回類型,等等辐棒。
一個(gè)類型的訪問級別也會(huì)影響到類型成員(屬性病曾、方法、構(gòu)造器漾根、下標(biāo))的默認(rèn)訪問級別知态。如果你將類型指定為 private 或者 fileprivate 級別,那么該類型的所有成員的默認(rèn)訪問級別也會(huì)變成 private 或者 fileprivate 級別立叛。如果你將類型指定為公開或者 internal (或者不明確指定訪問級別负敏,而使用默認(rèn)的 internal ),那么該類型的所有成員的默認(rèn)訪問級別將是內(nèi)部訪問秘蛇。
重點(diǎn)
上面提到其做,一個(gè) public 類型的所有成員的訪問級別默認(rèn)為 internal 級別,而不是 public 級別。如果你想將某個(gè)成員指定為 public 級別,那么你必須顯式指定巧颈。這樣做的好處是姥闭,在你定義公共接口的時(shí)候,可以明確地選擇哪些接口是需要公開的皂贩,哪些是內(nèi)部使用的,避免不小心將內(nèi)部使用的接口公開。
public class SomePublicClass { // 顯式 public 類
public var somePublicProperty = 0 // 顯式 public 類成員
var someInternalProperty = 0 // 隱式 internal 類成員
fileprivate func someFilePrivateMethod() {} // 顯式 fileprivate 類成員
private func somePrivateMethod() {} // 顯式 private 類成員
}
class SomeInternalClass { // 隱式 internal 類
var someInternalProperty = 0 // 隱式 internal 類成員
fileprivate func someFilePrivateMethod() {} // 顯式 fileprivate 類成員
private func somePrivateMethod() {} // 顯式 private 類成員
}
fileprivate class SomeFilePrivateClass { // 顯式 fileprivate 類
func someFilePrivateMethod() {} // 隱式 fileprivate 類成員
private func somePrivateMethod() {} // 顯式 private 類成員
}
private class SomePrivateClass { // 顯式 private 類
func somePrivateMethod() {} // 隱式 private 類成員
}
```swift
<a name="tuple_types"></a>
### 元組類型
元組的訪問級別將由元組中訪問級別最嚴(yán)格的類型來決定罚渐。例如,如果你構(gòu)建了一個(gè)包含兩種不同類型的元組驯妄,其中一個(gè)類型為 `internal`荷并,另一個(gè)類型為 `private`,那么這個(gè)元組的訪問級別為 `private`青扔。
> 注意
>
> 元組不同于類源织、結(jié)構(gòu)體翩伪、枚舉、函數(shù)那樣有單獨(dú)的定義谈息。元組的訪問級別是在它被使用時(shí)自動(dòng)推斷出的缘屹,而無法明確指定。
<a name="function_types"></a>
### 函數(shù)類型
函數(shù)的訪問級別根據(jù)訪問級別最嚴(yán)格的參數(shù)類型或返回類型的訪問級別來決定侠仇。但是囊颅,如果這種訪問級別不符合函數(shù)定義所在環(huán)境的默認(rèn)訪問級別,那么就需要明確地指定該函數(shù)的訪問級別傅瞻。
下面的例子定義了一個(gè)名為 `someFunction()` 的全局函數(shù)踢代,并且沒有明確地指定其訪問級別。也許你會(huì)認(rèn)為該函數(shù)應(yīng)該擁有默認(rèn)的訪問級別 `internal`嗅骄,但事實(shí)并非如此胳挎。事實(shí)上,如果按下面這種寫法溺森,代碼將無法通過編譯:
```swift
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// 此處是函數(shù)實(shí)現(xiàn)部分
}
我們可以看到慕爬,這個(gè)函數(shù)的返回類型是一個(gè)元組,該元組中包含兩個(gè)自定義的類屏积。其中一個(gè)類的訪問級別是 internal医窿,另一個(gè)的訪問級別是 private,所以根據(jù)元組訪問級別的原則炊林,該元組的訪問級別是 private(元組的訪問級別與元組中訪問級別最低的類型一致)姥卢。
因?yàn)樵摵瘮?shù)返回類型的訪問級別是 private,所以你必須使用 private 修飾符渣聚,明確指定該函數(shù)的訪問級別:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// 此處是函數(shù)實(shí)現(xiàn)部分
}
將該函數(shù)指定為 public 或 internal独榴,或者使用默認(rèn)的訪問級別 internal 都是錯(cuò)誤的,因?yàn)槿绻言摵瘮?shù)當(dāng)做 public 或 internal 級別來使用的話奕枝,可能會(huì)無法訪問 private 級別的返回值棺榔。
枚舉類型
枚舉成員的訪問級別和該枚舉類型相同,你不能為枚舉成員單獨(dú)指定不同的訪問級別隘道。
比如下面的例子症歇,枚舉 CompassPoint 被明確指定為 public,那么它的成員 North谭梗、South忘晤、East、West 的訪問級別同樣也是 public:
public enum CompassPoint {
case North
case South
case East
case West
}
原始值和關(guān)聯(lián)值
枚舉定義中的任何原始值或關(guān)聯(lián)值的類型的訪問級別至少不能低于枚舉類型的訪問級別默辨。例如德频,你不能在一個(gè) internal 的枚舉中定義 private 的原始值類型苍息。
嵌套類型
如果在 private 的類型中定義嵌套類型缩幸,那么該嵌套類型就自動(dòng)擁有 private 訪問級別壹置。如果在 public 或者 internal 級別的類型中定義嵌套類型,那么該嵌套類型自動(dòng)擁有 internal 訪問級別表谊。如果想讓嵌套類型擁有 public 訪問級別钞护,那么需要明確指定該嵌套類型的訪問級別。
子類
子類的訪問級別不得高于父類的訪問級別爆办。例如难咕,父類的訪問級別是 internal,子類的訪問級別就不能是 public距辆。
此外余佃,你可以在符合當(dāng)前訪問級別的條件下重寫任意類成員(方法、屬性跨算、構(gòu)造器爆土、下標(biāo)等)。
可以通過重寫為繼承來的類成員提供更高的訪問級別诸蚕。下面的例子中步势,類 A 的訪問級別是 public,它包含一個(gè)方法 someMethod()背犯,訪問級別為 private坏瘩。類 B 繼承自類 A,訪問級別為 internal漠魏,但是在類 B 中重寫了類 A 中訪問級別為 private 的方法 someMethod()倔矾,并重新指定為 internal 級別。通過這種方式柱锹,我們就可以將某類中 private 級別的類成員重新指定為更高的訪問級別破讨,以便其他人使用:
public class A {
private func someMethod() {}
}
internal class B: A {
override internal func someMethod() {}
}
我們甚至可以在子類中,用子類成員去訪問訪問級別更低的父類成員奕纫,只要這一操作在相應(yīng)訪問級別的限制范圍內(nèi)(也就是說提陶,在同一源文件中訪問父類 private 級別的成員,在同一模塊內(nèi)訪問父類 internal 級別的成員):
public class A {
private func someMethod() {}
}
internal class B: A {
override internal func someMethod() {
super.someMethod()
}
}
因?yàn)楦割?A 和子類 B 定義在同一個(gè)源文件中匹层,所以在子類 B 可以在重寫的 someMethod() 方法中調(diào)用 super.someMethod()隙笆。
常量、變量升筏、屬性撑柔、下標(biāo)
常量、變量您访、屬性不能擁有比它們的類型更高的訪問級別铅忿。例如,你不能定義一個(gè) public 級別的屬性灵汪,但是它的類型卻是 private 級別的檀训。同樣柑潦,下標(biāo)也不能擁有比索引類型或返回類型更高的訪問級別。
如果常量峻凫、變量渗鬼、屬性、下標(biāo)的類型是 private 級別的荧琼,那么它們必須明確指定訪問級別為 private:
private var privateInstance = SomePrivateClass()
Getter 和 Setter
常量譬胎、變量、屬性命锄、下標(biāo)的 Getters 和 Setters 的訪問級別和它們所屬類型的訪問級別相同堰乔。
Setter 的訪問級別可以低于對應(yīng)的 Getter 的訪問級別,這樣就可以控制變量脐恩、屬性或下標(biāo)的讀寫權(quán)限浩考。在 var 或 subscript 關(guān)鍵字之前,你可以通過 fileprivate(set)被盈,private(set) 或 internal(set) 為它們的寫入權(quán)限指定更低的訪問級別析孽。
注意
這個(gè)規(guī)則同時(shí)適用于存儲型屬性和計(jì)算型屬性。即使你不明確指定存儲型屬性的 Getter 和 Setter只怎,Swift 也會(huì)隱式地為其創(chuàng)建 Getter 和 Setter袜瞬,用于訪問該屬性的后備存儲。使用 fileprivate(set)身堡,private(set) 和 internal(set) 可以改變 Setter 的訪問級別邓尤,這對計(jì)算型屬性也同樣適用。
下面的例子中定義了一個(gè)名為 TrackedString 的結(jié)構(gòu)體贴谎,它記錄了 value 屬性被修改的次數(shù):
struct TrackedString {
private(set) var numberOfEdits = 0
var value: String = "" {
didSet {
numberOfEdits += 1
}
}
}
TrackedString 結(jié)構(gòu)體定義了一個(gè)用于存儲 String 值的屬性 value汞扎,并將初始值設(shè)為 ""(一個(gè)空字符串)。該結(jié)構(gòu)體還定義了另一個(gè)用于存儲 Int 值的屬性 numberOfEdits擅这,它用于記錄屬性 value 被修改的次數(shù)澈魄。這個(gè)功能通過屬性 value 的 didSet 觀察器實(shí)現(xiàn),每當(dāng)給 value 賦新值時(shí)就會(huì)調(diào)用 didSet 方法仲翎,然后將 numberOfEdits 的值加一痹扇。
結(jié)構(gòu)體 TrackedString 和它的屬性 value 都沒有顯式地指定訪問級別,所以它們都是用默認(rèn)的訪問級別 internal溯香。但是該結(jié)構(gòu)體的 numberOfEdits 屬性使用了 private(set) 修飾符鲫构,這意味著 numberOfEdits 屬性只能在結(jié)構(gòu)體的定義中進(jìn)行賦值。numberOfEdits 屬性的 Getter 依然是默認(rèn)的訪問級別 internal玫坛,但是 Setter 的訪問級別是 private结笨,這表示該屬性只能在內(nèi)部修改,而在結(jié)構(gòu)體的外部則表現(xiàn)為一個(gè)只讀屬性。
如果你實(shí)例化 TrackedString 結(jié)構(gòu)體炕吸,并多次對 value 屬性的值進(jìn)行修改伐憾,你就會(huì)看到 numberOfEdits 的值會(huì)隨著修改次數(shù)而變化:
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)")
雖然你可以在其他的源文件中實(shí)例化該結(jié)構(gòu)體并且獲取到 numberOfEdits 屬性的值,但是你不能對其進(jìn)行賦值算途。這一限制保護(hù)了該記錄功能的實(shí)現(xiàn)細(xì)節(jié)塞耕,同時(shí)還提供了方便的訪問方式蚀腿。
你可以在必要時(shí)為 Getter 和 Setter 顯式指定訪問級別嘴瓤。下面的例子將 TrackedString 結(jié)構(gòu)體明確指定為了 public 訪問級別。結(jié)構(gòu)體的成員(包括 numberOfEdits 屬性)擁有默認(rèn)的訪問級別 internal莉钙。你可以結(jié)合 public 和 private(set) 修飾符把結(jié)構(gòu)體中的 numberOfEdits 屬性的 Getter 的訪問級別設(shè)置為 public廓脆,而 Setter 的訪問級別設(shè)置為 private:
public struct TrackedString {
public private(set) var numberOfEdits = 0
public var value: String = "" {
didSet {
numberOfEdits += 1
}
}
public init() {}
}
構(gòu)造器
自定義構(gòu)造器的訪問級別可以低于或等于其所屬類型的訪問級別。唯一的例外是必要構(gòu)造器磁玉,它的訪問級別必須和所屬類型的訪問級別相同停忿。
如同函數(shù)或方法的參數(shù),構(gòu)造器參數(shù)的訪問級別也不能低于構(gòu)造器本身的訪問級別蚊伞。
默認(rèn)構(gòu)造器
Swift 會(huì)為結(jié)構(gòu)體和類提供一個(gè)默認(rèn)的無參數(shù)的構(gòu)造器席赂,只要它們?yōu)樗写鎯π蛯傩栽O(shè)置了默認(rèn)初始值,并且未提供自定義的構(gòu)造器时迫。
默認(rèn)構(gòu)造器的訪問級別與所屬類型的訪問級別相同颅停,除非類型的訪問級別是 public。如果一個(gè)類型被指定為 public 級別掠拳,那么默認(rèn)構(gòu)造器的訪問級別將為 internal癞揉。如果你希望一個(gè) public 級別的類型也能在其他模塊中使用這種無參數(shù)的默認(rèn)構(gòu)造器,你只能自己提供一個(gè) public 訪問級別的無參數(shù)構(gòu)造器溺欧。
結(jié)構(gòu)體默認(rèn)的成員逐一構(gòu)造器
如果結(jié)構(gòu)體中任意存儲型屬性的訪問級別為 private喊熟,那么該結(jié)構(gòu)體默認(rèn)的成員逐一構(gòu)造器的訪問級別就是 private。否則姐刁,這種構(gòu)造器的訪問級別依然是 internal芥牌。
如同前面提到的默認(rèn)構(gòu)造器,如果你希望一個(gè) public 級別的結(jié)構(gòu)體也能在其他模塊中使用其默認(rèn)的成員逐一構(gòu)造器聂使,你依然只能自己提供一個(gè) public 訪問級別的成員逐一構(gòu)造器胳泉。
協(xié)議
如果想為一個(gè)協(xié)議類型明確地指定訪問級別,在定義協(xié)議時(shí)指定即可岩遗。這將限制該協(xié)議只能在適當(dāng)?shù)脑L問級別范圍內(nèi)被采納扇商。
協(xié)議中的每一個(gè)要求都具有和該協(xié)議相同的訪問級別。你不能將協(xié)議中的要求設(shè)置為其他訪問級別宿礁。這樣才能確保該協(xié)議的所有要求對于任意采納者都將可用案铺。
注意
Swift 和 Objective-C 一樣,協(xié)議的一致性是全局的梆靖,也就是說控汉,在同一程序中笔诵,一個(gè)類型不可能用兩種不同的方式實(shí)現(xiàn)同一個(gè)協(xié)議。
Extension
Extension 可以在訪問級別允許的情況下對類姑子、結(jié)構(gòu)體乎婿、枚舉進(jìn)行擴(kuò)展。Extension 的成員具有和原始類型成員一致的訪問級別街佑。例如谢翎,你使用 extension 擴(kuò)展了一個(gè) public
或者 internal
類型,extension 中的成員就默認(rèn)使用 internal
訪問級別沐旨,和原始類型中的成員一致森逮。如果你使用 extension 擴(kuò)展了一個(gè) private
類型,則 extension 的成員默認(rèn)使用 private
訪問級別磁携。
或者褒侧,你可以明確指定 extension 的訪問級別(例如,private extension
)谊迄,從而給該 extension 中的所有成員指定一個(gè)新的默認(rèn)訪問級別闷供。這個(gè)新的默認(rèn)訪問級別仍然可以被單獨(dú)指定的訪問級別所覆蓋。
如果你使用 extension 來遵循協(xié)議的話统诺,就不能顯式地聲明 extension 的訪問級別歪脏。extension 每個(gè) protocol 要求的實(shí)現(xiàn)都默認(rèn)使用 protocol 的訪問級別。
Extension 的私有成員
擴(kuò)展同一文件內(nèi)的類篙议,結(jié)構(gòu)體或者枚舉唾糯,extension 里的代碼會(huì)表現(xiàn)得跟聲明在原類型里的一模一樣。也就是說你可以這樣:
- 在類型的聲明里聲明一個(gè)私有成員鬼贱,在同一文件的 extension 里訪問移怯。
- 在 extension 里聲明一個(gè)私有成員,在同一文件的另一個(gè) extension 里訪問这难。
- 在 extension 里聲明一個(gè)私有成員舟误,在同一文件的類型聲明里訪問。
這意味著你可以像組織的代碼去使用 extension姻乓,而且不受私有成員的影響嵌溢。例如,給定下面這樣一個(gè)簡單的協(xié)議:
protocol SomeProtocol {
func doSomething() {}
}
你可以使用 extension 來遵守協(xié)議蹋岩,就想這樣:
struct SomeStruct {
private var privateVariable = 12
}
extension SomeStruct: SomeProtocol {
func doSomething() {
print(privateVariable)
}
}
泛型
泛型類型或泛型函數(shù)的訪問級別取決于泛型類型或泛型函數(shù)本身的訪問級別赖草,還需結(jié)合類型參數(shù)的類型約束的訪問級別,根據(jù)這些訪問級別中的最低訪問級別來確定剪个。
類型別名
你定義的任何類型別名都會(huì)被當(dāng)作不同的類型秧骑,以便于進(jìn)行訪問控制。類型別名的訪問級別不可高于其表示的類型的訪問級別。例如乎折,private 級別的類型別名可以作為 private绒疗、file-private、internal骂澄、public 或者 open 類型的別名吓蘑,但是 public 級別的類型別名只能作為 public 類型的別名,不能作為 internal坟冲、file-private 或 private 類型的別名磨镶。
注意
這條規(guī)則也適用于為滿足協(xié)議一致性而將類型別名用于關(guān)聯(lián)類型的情況。