訪問控制可以限定其它源文件或模塊對(duì)你的代碼的訪問。這個(gè)特性可以讓你隱藏代碼的實(shí)現(xiàn)細(xì)節(jié),并且能提供一個(gè)接口來讓別人訪問和使用你的代碼。
你可以明確地給單個(gè)類型(類、結(jié)構(gòu)體、枚舉)設(shè)置訪問級(jí)別,也可以給這些類型的屬性、方法、構(gòu)造器、下標(biāo)等設(shè)置訪問級(jí)別。協(xié)議也可以被限定在一定訪問級(jí)別的范圍內(nèi)使用,包括協(xié)議里的全局常量、變量和函數(shù)。
Swift 不僅提供了多種不同的訪問級(jí)別,還為某些典型場(chǎng)景提供了默認(rèn)的訪問級(jí)別,這樣就不需要我們?cè)诿慷未a中都顯式聲明訪問級(jí)別。如果你只是開發(fā)一個(gè)單 target 的應(yīng)用程序,完全可以不用顯式聲明代碼的訪問級(jí)別。
注意
為了簡單起見,對(duì)于代碼中可以設(shè)置訪問級(jí)別的特性(屬性、基本類型、函數(shù)等),在下面的章節(jié)中我們會(huì)統(tǒng)一稱之為“實(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 模塊中的源代碼文件(實(shí)際上,源文件屬于一個(gè)應(yīng)用程序或框架)。盡管我們一般會(huì)將不同的類型分別定義在不同的源文件中,但是同一個(gè)源文件也可以包含多個(gè)類型、函數(shù)等的定義。
Swift 為代碼中的實(shí)體提供了五種不同的訪問級(jí)別。這些訪問級(jí)別不僅與源文件中定義的實(shí)體相關(guān),同時(shí)也與源文件所屬的模塊相關(guān)。
open 為最高訪問級(jí)別(限制最少),private 為最低訪問級(jí)別(限制最多)。
open 只能作用于類和類的成員,它和 public 的區(qū)別主要在于 open 限定的類和成員能夠在模塊外能被繼承和重寫,在下面的 子類 這一節(jié)中有詳解。將類的訪問級(jí)別顯示指定為 open
表明你已經(jīng)設(shè)計(jì)好了類的代碼,并且充分考慮過這個(gè)類在其他模塊中用作父類時(shí)的影響。
Swift 中的訪問級(jí)別遵循一個(gè)基本原則:實(shí)體不能定義在具有更低訪問級(jí)別(更嚴(yán)格)的實(shí)體中。
例如:
關(guān)于此原則在各種情況下的具體表現(xiàn),將在下文有所體現(xiàn)。
你代碼中所有的實(shí)體,如果你不顯式的指定它們的訪問級(jí)別,那么它們將都有一個(gè) internal
的默認(rèn)訪問級(jí)別,(有一些例外情況,本文稍后會(huì)有說明)。因此,多數(shù)情況下你不需要顯示指定實(shí)體的訪問級(jí)別。
當(dāng)你編寫一個(gè)單 target 應(yīng)用程序時(shí),應(yīng)用的所有功能都是為該應(yīng)用服務(wù),而不需要提供給其他應(yīng)用或者模塊使用,所以你不需要明確設(shè)置訪問級(jí)別,使用默認(rèn)的訪問級(jí)別 internal 即可。但是,你也可以使用 fileprivate
或 private
訪問級(jí)別,用于隱藏一些功能的實(shí)現(xiàn)細(xì)節(jié)。
當(dāng)你開發(fā)框架時(shí),就需要把一些對(duì)外的接口定義為 open 或 public 訪問級(jí)別,以便使用者導(dǎo)入該框架后可以正常使用其功能。這些被你定義為對(duì)外的接口,就是這個(gè)框架的 API。
注意
框架的內(nèi)部實(shí)現(xiàn)仍然可以使用默認(rèn)的訪問級(jí)別
internal
,當(dāng)你需要對(duì)框架內(nèi)部其它部分隱藏細(xì)節(jié)時(shí)可以使用private
或fileprivate
。對(duì)于框架的對(duì)外 API 部分,你就需要將它們?cè)O(shè)置為open
或public
了。
當(dāng)你的應(yīng)用程序包含單元測(cè)試 target 時(shí),為了測(cè)試,測(cè)試模塊需要訪問應(yīng)用程序模塊中的代碼。默認(rèn)情況下只有 open
或 public
級(jí)別的實(shí)體才可以被其他模塊訪問。然而,如果在導(dǎo)入應(yīng)用程序模塊的語句前使用 @testable
特性,然后在允許測(cè)試的編譯設(shè)置(Build Options -> Enable Testability
)下編譯這個(gè)應(yīng)用程序模塊,單元測(cè)試目標(biāo)就可以訪問應(yīng)用程序模塊中所有內(nèi)部級(jí)別的實(shí)體。
通過修飾符 open
、public
、internal
、fileprivate
、private
來聲明實(shí)體的訪問級(jí)別:
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)的訪問級(jí)別為 internal
,可以查閱 默認(rèn)訪問級(jí)別 這一節(jié)。這意味著在不使用修飾符顯式聲明訪問級(jí)別的情況下,SomeInternalClass
和 someInternalConstant
的訪問級(jí)別是 internal
:
class SomeInternalClass {} // 隱式 internal
var someInternalConstant = 0 // 隱式 internal
如果想為一個(gè)自定義類型指定訪問級(jí)別,在定義類型時(shí)進(jìn)行指定即可。新類型只能在它的訪問級(jí)別限制范圍內(nèi)使用。例如,你定義了一個(gè) fileprivate
級(jí)別的類,那這個(gè)類就只能在定義它的源文件中使用,可以作為屬性類型、函數(shù)參數(shù)類型或者返回類型等等。
一個(gè)類型的訪問級(jí)別也會(huì)影響到類型成員(屬性、方法、構(gòu)造器、下標(biāo))的默認(rèn)訪問級(jí)別。如果你將類型指定為 private
或者 fileprivate
級(jí)別,那么該類型的所有成員的默認(rèn)訪問級(jí)別也會(huì)變成 private
或者 fileprivate
級(jí)別。如果你將類型指定為 internal
或 public
(或者不明確指定訪問級(jí)別,而使用默認(rèn)的 internal
),那么該類型的所有成員的默認(rèn)訪問級(jí)別將是 internal
。
重點(diǎn)
上面提到,一個(gè)
public
類型的所有成員的訪問級(jí)別默認(rèn)為internal
級(jí)別,而不是public
級(jí)別。如果你想將某個(gè)成員指定為public
級(jí)別,那么你必須顯式指定。這樣做的好處是,在你定義公共接口的時(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 類成員
}
元組的訪問級(jí)別將由元組中訪問級(jí)別最嚴(yán)格的類型來決定。例如,如果你構(gòu)建了一個(gè)包含兩種不同類型的元組,其中一個(gè)類型為 internal
,另一個(gè)類型為 private
,那么這個(gè)元組的訪問級(jí)別為 private
。
注意
元組不同于類、結(jié)構(gòu)體、枚舉、函數(shù)那樣有單獨(dú)的定義。一個(gè)元組的訪問級(jí)別由元組中元素的訪問級(jí)別來決定的,不能被顯示指定。
函數(shù)的訪問級(jí)別根據(jù)訪問級(jí)別最嚴(yán)格的參數(shù)類型或返回類型的訪問級(jí)別來決定。但是,如果這種訪問級(jí)別不符合函數(shù)定義所在環(huán)境的默認(rèn)訪問級(jí)別,那么就需要明確地指定該函數(shù)的訪問級(jí)別。
下面的例子定義了一個(gè)名為 someFunction()
的全局函數(shù),并且沒有明確地指定其訪問級(jí)別。也許你會(huì)認(rèn)為該函數(shù)應(yīng)該擁有默認(rèn)的訪問級(jí)別 internal
,但事實(shí)并非如此。事實(shí)上,如果按下面這種寫法,代碼將無法通過編譯:
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// 此處是函數(shù)實(shí)現(xiàn)部分
}
我們可以看到,這個(gè)函數(shù)的返回類型是一個(gè)元組,該元組中包含兩個(gè)自定義的類(可查閱 自定義類型)。其中一個(gè)類的訪問級(jí)別是 internal
,另一個(gè)的訪問級(jí)別是 private
,所以根據(jù)元組訪問級(jí)別的原則,該元組的訪問級(jí)別是 private
(元組的訪問級(jí)別與元組中訪問級(jí)別最低的類型一致)。
因?yàn)樵摵瘮?shù)返回類型的訪問級(jí)別是 private
,所以你必須使用 private
修飾符來明確指定該函數(shù)的訪問級(jí)別:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// 此處是函數(shù)實(shí)現(xiàn)部分
}
將該函數(shù)指定為 public
或 internal
,或者使用默認(rèn)的訪問級(jí)別 internal
都是錯(cuò)誤的,因?yàn)槿绻言摵瘮?shù)當(dāng)做 public
或 internal
級(jí)別來使用的話,可能會(huì)無法訪問 private
級(jí)別的返回值。
枚舉成員的訪問級(jí)別和該枚舉類型相同,你不能為枚舉成員單獨(dú)指定不同的訪問級(jí)別。
比如下面的例子,枚舉 CompassPoint
被明確指定為 public
,那么它的成員 north
、south
、east
、west
的訪問級(jí)別同樣也是 public
:
public enum CompassPoint {
case north
case south
case east
case west
}
枚舉定義中的任何原始值或關(guān)聯(lián)值的類型的訪問級(jí)別至少不能低于枚舉類型的訪問級(jí)別。例如,你不能在一個(gè) internal
的枚舉中定義 private
的原始值類型。
嵌套類型的訪問級(jí)別和包含它的類型的訪問級(jí)別相同,嵌套類型是 public 的情況除外。在一個(gè) public 的類型中定義嵌套類型,那么嵌套類型自動(dòng)擁有 internal
的訪問級(jí)別。如果你想讓嵌套類型擁有 public
訪問級(jí)別,那么必須顯式指定該嵌套類型的訪問級(jí)別為 public。
你可以繼承同一模塊中的所有有訪問權(quán)限的類,也可以繼承不同模塊中被 open 修飾的類。一個(gè)子類的訪問級(jí)別不得高于父類的訪問級(jí)別。例如,父類的訪問級(jí)別是 internal
,子類的訪問級(jí)別就不能是 public
。
此外,在同一模塊中,你可以在符合當(dāng)前訪問級(jí)別的條件下重寫任意類成員(方法、屬性、構(gòu)造器、下標(biāo)等)。在不同模塊中,你可以重寫類中被 open 修飾的成員。
可以通過重寫給所繼承類的成員提供更高的訪問級(jí)別。下面的例子中,類 A
的訪問級(jí)別是 public
,它包含一個(gè)方法 someMethod()
,訪問級(jí)別為 fileprivate
。類 B
繼承自類 A
,訪問級(jí)別為 internal
,但是在類 B
中重寫了類 A
中訪問級(jí)別為 fileprivate
的方法 someMethod()
,并重新指定為 internal
級(jí)別。通過這種方式,我們就可以將某類中 fileprivate
級(jí)別的類成員重新指定為更高的訪問級(jí)別,以便其他人使用:
public class A {
fileprivate func someMethod() {}
}
internal class B: A {
override internal func someMethod() {}
}
我們甚至可以在子類中,用子類成員去訪問訪問級(jí)別更低的父類成員,只要這一操作在相應(yīng)訪問級(jí)別的限制范圍內(nèi)(也就是說,在同一源文件中訪問父類 fileprivate
級(jí)別的成員,在同一模塊內(nèi)訪問父類 internal
級(jí)別的成員):
public class A {
fileprivate func someMethod() {}
}
internal class B: A {
override internal func someMethod() {
super.someMethod()
}
}
因?yàn)楦割?A
和子類 B
定義在同一個(gè)源文件中,所以在子類 B
可以在重寫的 someMethod()
方法中調(diào)用 super.someMethod()
。
常量、變量、屬性不能擁有比它們的類型更高的訪問級(jí)別。例如,你不能定義一個(gè) public
級(jí)別的屬性,但是它的類型卻是 private
級(jí)別的。同樣,下標(biāo)也不能擁有比索引類型或返回類型更高的訪問級(jí)別。
如果常量、變量、屬性、下標(biāo)的類型是 private
級(jí)別的,那么它們必須明確指定訪問級(jí)別為 private
:
private var privateInstance = SomePrivateClass()
常量、變量、屬性、下標(biāo)的 Getters
和 Setters
的訪問級(jí)別和它們所屬類型的訪問級(jí)別相同。
Setter
的訪問級(jí)別可以低于對(duì)應(yīng)的 Getter
的訪問級(jí)別,這樣就可以控制變量、屬性或下標(biāo)的讀寫權(quán)限。在 var
或 subscript
關(guān)鍵字之前,你可以通過 fileprivate(set)
,private(set)
或 internal(set)
為它們的寫入權(quán)限指定更低的訪問級(jí)別。
注意
這個(gè)規(guī)則同時(shí)適用于存儲(chǔ)型屬性和計(jì)算型屬性。即使你不明確指定存儲(chǔ)型屬性的
Getter
和Setter
,Swift 也會(huì)隱式地為其創(chuàng)建Getter
和Setter
,用于訪問該屬性的存儲(chǔ)內(nèi)容。使用fileprivate(set)
,private(set)
和internal(set)
可以改變Setter
的訪問級(jí)別,這對(duì)計(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è)用于存儲(chǔ) String
值的屬性 value
,并將初始值設(shè)為 ""
(一個(gè)空字符串)。該結(jié)構(gòu)體還定義了另一個(gè)用于存儲(chǔ) Int
值的屬性 numberOfEdits
,它用于記錄屬性 value
被修改的次數(shù)。這個(gè)功能通過屬性 value
的 didSet
觀察器實(shí)現(xiàn),每當(dāng)給 value
賦新值時(shí)就會(huì)調(diào)用 didSet
方法,然后將 numberOfEdits
的值加一。
結(jié)構(gòu)體 TrackedString
和它的屬性 value
都沒有顯式地指定訪問級(jí)別,所以它們都是用默認(rèn)的訪問級(jí)別 internal
。但是該結(jié)構(gòu)體的 numberOfEdits
屬性使用了 private(set)
修飾符,這意味著 numberOfEdits
屬性只能在結(jié)構(gòu)體的定義中進(jìn)行賦值。numberOfEdits
屬性的 Getter
依然是默認(rèn)的訪問級(jí)別 internal
,但是 Setter
的訪問級(jí)別是 private
,這表示該屬性只能在內(nèi)部修改,而在結(jié)構(gòu)體的外部則表現(xiàn)為一個(gè)只讀屬性。
如果你實(shí)例化 TrackedString
結(jié)構(gòu)體,并多次對(duì) 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)")
// 打印“The number of edits is 3”
雖然你可以在其他的源文件中實(shí)例化該結(jié)構(gòu)體并且獲取到 numberOfEdits
屬性的值,但是你不能對(duì)其進(jìn)行賦值。這一限制保護(hù)了該記錄功能的實(shí)現(xiàn)細(xì)節(jié),同時(shí)還提供了方便的訪問方式。
你可以在必要時(shí)為 Getter
和 Setter
顯式指定訪問級(jí)別。下面的例子將 TrackedString
結(jié)構(gòu)體明確指定為了 public
訪問級(jí)別。結(jié)構(gòu)體的成員(包括 numberOfEdits
屬性)擁有默認(rèn)的訪問級(jí)別 internal
。你可以結(jié)合 public
和 private(set)
修飾符把結(jié)構(gòu)體中的 numberOfEdits
屬性的 Getter
的訪問級(jí)別設(shè)置為 public
,而 Setter
的訪問級(jí)別設(shè)置為 private
:
public struct TrackedString {
public private(set) var numberOfEdits = 0
public var value: String = "" {
didSet {
numberOfEdits += 1
}
}
public init() {}
}
自定義構(gòu)造器的訪問級(jí)別可以低于或等于其所屬類型的訪問級(jí)別。唯一的例外是 必要構(gòu)造器,它的訪問級(jí)別必須和所屬類型的訪問級(jí)別相同。
如同函數(shù)或方法的參數(shù),構(gòu)造器參數(shù)的訪問級(jí)別也不能低于構(gòu)造器本身的訪問級(jí)別。
如 默認(rèn)構(gòu)造器 所述,Swift 會(huì)為結(jié)構(gòu)體和類提供一個(gè)默認(rèn)的無參數(shù)的構(gòu)造器,只要它們?yōu)樗写鎯?chǔ)型屬性設(shè)置了默認(rèn)初始值,并且未提供自定義的構(gòu)造器。
默認(rèn)構(gòu)造器的訪問級(jí)別與所屬類型的訪問級(jí)別相同,除非類型的訪問級(jí)別是 public
。如果一個(gè)類型被指定為 public
級(jí)別,那么默認(rèn)構(gòu)造器的訪問級(jí)別將為 internal
。如果你希望一個(gè) public
級(jí)別的類型也能在其他模塊中使用這種無參數(shù)的默認(rèn)構(gòu)造器,你只能自己提供一個(gè) public
訪問級(jí)別的無參數(shù)構(gòu)造器。
如果結(jié)構(gòu)體中任意存儲(chǔ)型屬性的訪問級(jí)別為 private
,那么該結(jié)構(gòu)體默認(rèn)的成員逐一構(gòu)造器的訪問級(jí)別就是 private
。否則,這種構(gòu)造器的訪問級(jí)別依然是 internal
。
如同前面提到的默認(rèn)構(gòu)造器,如果你希望一個(gè) public
級(jí)別的結(jié)構(gòu)體也能在其他模塊中使用其默認(rèn)的成員逐一構(gòu)造器,你依然只能自己提供一個(gè) public
訪問級(jí)別的成員逐一構(gòu)造器。
如果想為一個(gè)協(xié)議類型明確地指定訪問級(jí)別,在聲明協(xié)議時(shí)指定即可。這將限制該協(xié)議只能在適當(dāng)?shù)脑L問級(jí)別范圍內(nèi)被遵循。
協(xié)議中的每個(gè)方法或?qū)傩远急仨毦哂泻驮搮f(xié)議相同的訪問級(jí)別。你不能將協(xié)議中的方法或?qū)傩栽O(shè)置為其他訪問級(jí)別。這樣才能確保該協(xié)議的所有方法或?qū)傩詫?duì)于任意遵循者都可用。
注意
如果你定義了一個(gè)
public
訪問級(jí)別的協(xié)議,那么該協(xié)議的所有實(shí)現(xiàn)也會(huì)是public
訪問級(jí)別。這一點(diǎn)不同于其他類型,例如,類型是public
訪問級(jí)別時(shí),其成員的訪問級(jí)別卻只是internal
。
如果定義了一個(gè)繼承自其他協(xié)議的新協(xié)議,那么新協(xié)議擁有的訪問級(jí)別最高也只能和被繼承協(xié)議的訪問級(jí)別相同。例如,你不能將繼承自 internal
協(xié)議的新協(xié)議訪問級(jí)別指定為 public
協(xié)議。
一個(gè)類型可以遵循比它級(jí)別更低的協(xié)議。例如,你可以定義一個(gè) public
級(jí)別類型,它能在別的模塊中使用,但是如果它遵循一個(gè) internal
協(xié)議,這個(gè)遵循的部分就只能在這個(gè) internal
協(xié)議所在的模塊中使用。
遵循協(xié)議時(shí)的上下文級(jí)別是類型和協(xié)議中級(jí)別最小的那個(gè)。如果一個(gè)類型是 public
級(jí)別,但它要遵循的協(xié)議是 internal
級(jí)別,那么這個(gè)類型對(duì)該協(xié)議的遵循上下文就是 internal
級(jí)別。
當(dāng)你編寫或擴(kuò)展一個(gè)類型讓它遵循一個(gè)協(xié)議時(shí),你必須確保該類型對(duì)協(xié)議的每一個(gè)要求的實(shí)現(xiàn),至少與遵循協(xié)議的上下文級(jí)別一致。例如,一個(gè) public
類型遵循一個(gè) internal
協(xié)議,這個(gè)類型對(duì)協(xié)議的所有實(shí)現(xiàn)至少都應(yīng)是 internal
級(jí)別的。
注意
Swift 和 Objective-C 一樣,協(xié)議遵循是全局的,也就是說,在同一程序中,一個(gè)類型不可能用兩種不同的方式實(shí)現(xiàn)同一個(gè)協(xié)議。
Extension 可以在訪問級(jí)別允許的情況下對(duì)類、結(jié)構(gòu)體、枚舉進(jìn)行擴(kuò)展。Extension 的新增成員具有和原始類型成員一致的訪問級(jí)別。例如,你使用 extension 擴(kuò)展了一個(gè) public
或者 internal
類型,則 extension 中的成員就默認(rèn)使用 internal
訪問級(jí)別。如果你使用 extension 擴(kuò)展一個(gè) fileprivate
類型,則 extension 中的成員默認(rèn)使用 fileprivate
訪問級(jí)別。如果你使用 extension 擴(kuò)展了一個(gè) private
類型,則 extension 的成員默認(rèn)使用 private
訪問級(jí)別。
或者,你可以通過修飾語重新指定 extension 的默認(rèn)訪問級(jí)別(例如,private
),從而給該 extension 中的所有成員指定一個(gè)新的默認(rèn)訪問級(jí)別。這個(gè)新的默認(rèn)訪問級(jí)別仍然可以被單獨(dú)成員指定的訪問級(jí)別所覆蓋。
如果你使用 extension 來遵循協(xié)議的話,就不能顯式地聲明 extension 的訪問級(jí)別。extension 每個(gè) protocol 要求的實(shí)現(xiàn)都默認(rèn)使用 protocol 的訪問級(jí)別。
擴(kuò)展同一文件內(nèi)的類,結(jié)構(gòu)體或者枚舉,extension 里的代碼會(huì)表現(xiàn)得跟聲明在原類型里的一模一樣。也就是說你可以這樣:
這意味著你可以使用 extension 來組織你的代碼,而且不受私有成員的影響。例如,給定下面這樣一個(gè)簡單的協(xié)議:
protocol SomeProtocol {
func doSomething()
}
你可以使用 extension 來遵循協(xié)議,就像這樣:
struct SomeStruct {
private var privateVariable = 12
}
extension SomeStruct: SomeProtocol {
func doSomething() {
print(privateVariable)
}
}
泛型類型或泛型函數(shù)的訪問級(jí)別取決于泛型類型或泛型函數(shù)本身的訪問級(jí)別,還需結(jié)合類型參數(shù)的類型約束的訪問級(jí)別,根據(jù)這些訪問級(jí)別中的最低訪問級(jí)別來確定。
你定義的任何類型別名都會(huì)被當(dāng)作不同的類型,以便于進(jìn)行訪問控制。類型別名的訪問級(jí)別不可高于其表示的類型的訪問級(jí)別。例如,private
級(jí)別的類型別名可以作為 private
、fileprivate
、internal
、public
或者 open
類型的別名,但是 public
級(jí)別的類型別名只能作為 public
類型的別名,不能作為 internal
、fileprivate
或 private
類型的別名。
注意
這條規(guī)則也適用于為滿足協(xié)議遵循而將類型別名用于關(guān)聯(lián)類型的情況。