25 Access Control 訪問控制

訪問控制限制從其他源文件和模塊中的代碼訪問代碼的部分。該特性使您能夠隱藏代碼的實現(xiàn)細(xì)節(jié)酝惧,并指定可以訪問和使用代碼的首選接口渠啊。

您可以為各個類型(類、結(jié)構(gòu)和枚舉)以及屬于這些類型的屬性担孔、方法、初始化器和下標(biāo)分配特定的訪問級別吃警。協(xié)議可以限制在特定的上下文中糕篇,全局常量、變量和函數(shù)也可以酌心。

除了提供不同級別的訪問控制拌消,Swift還通過為典型場景提供默認(rèn)訪問級別,減少了指定顯式訪問控制級別的需要安券。實際上墩崩,如果您正在編寫一個單個 target 應(yīng)用程序氓英,您可能根本不需要指定顯式的訪問控制級別。

為了簡單起見鹦筹,下面幾節(jié)將代碼的各個方面(屬性铝阐、類型、函數(shù)等等)稱為“實體entities”铐拐。

Modules and Source Files 模塊和源文件

Swift的訪問控制模型基于模塊和源文件的概念徘键。

Module是一個代碼分發(fā)的單一單元——a framework or application作為一個單元構(gòu)建和發(fā)布,并且可以由另一個模塊使用Swift的import關(guān)鍵字導(dǎo)入遍蟋。

Xcode中的每個構(gòu)建目標(biāo)(如 app bundle 和 framework)在Swift中被視為一個單獨(dú)的模塊吹害。如果您將應(yīng)用程序代碼的各個方面作為一個獨(dú)立的框架組合在一起——可能是為了在多個應(yīng)用程序之間封裝和重用這些代碼——那么當(dāng)您在該框架中定義的所有內(nèi)容在應(yīng)用程序中導(dǎo)入和使用時,或者在另一個框架中使用時虚青,都將是一個單獨(dú)模塊的一部分赠制。

源文件是模塊中的單個Swift源代碼文件(實際上,是應(yīng)用程序或框架中的單個文件)挟憔。雖然在單獨(dú)的源文件中定義單個類型很常見钟些,但是一個源文件可以包含多個類型、函數(shù)等的定義绊谭。

Access Levels 訪問等級

Swift為代碼中的實體提供了五種不同的訪問級別政恍。
這些訪問級別相對于定義實體的源文件,也相對于源文件所屬的模塊达传。

  • openpublic 訪問允許實體在其定義模塊的任何源文件中使用篙耗,也可以在導(dǎo)入定義模塊的另一個模塊的源文件中使用。在指定框架的公共接口時宪赶,通常使用open或public關(guān)鍵字宗弯。下面會描述開放訪問和公共訪問之間的區(qū)別。

  • Internal 內(nèi)部訪問允許實體在其定義模塊的任何源文件中使用搂妻,但不能在該模塊之外的任何源文件中使用蒙保。在定義應(yīng)用程序或框架的內(nèi)部結(jié)構(gòu)時,通常使用內(nèi)部訪問欲主。

  • File-private 文件私有訪問將實體的使用限制為它自己定義的源文件邓厕。當(dāng)在整個文件中使用特定功能的實現(xiàn)細(xì)節(jié)時,使用file-private訪問隱藏這些細(xì)節(jié)。

  • Private 私有訪問將實體的使用限制為所包含的聲明,以及對同一文件中聲明的擴(kuò)展名的使用默刚。當(dāng)僅在單個聲明中使用特定功能塊的實現(xiàn)細(xì)節(jié)時,使用私有訪問隱藏這些細(xì)節(jié)昧互。

open 是最高(限制最少)的訪問級別,private 是最低(限制最多)的訪問級別。

open 訪問只適用于類和類成員敞掘,它與 public 訪問的區(qū)別如下:

  • 具有 public 訪問或任何更嚴(yán)格訪問級別的類只能在定義它們的模塊中子類化屿储。
  • 具有 public 訪問權(quán)限的類成員,或任何具有更嚴(yán)格訪問級別的類成員渐逃,只能由定義它們的模塊中的子類覆蓋。
  • open 類可以在定義它們的模塊中子類化民褂,也可以在導(dǎo)入它們定義的模塊的任何模塊中子類化茄菊。
  • open 類成員可以被定義它們的模塊中的子類覆蓋,也可以被導(dǎo)入定義它們的模塊的任何模塊覆蓋赊堪。

將一個類顯式地標(biāo)記為open表明您已經(jīng)考慮了使用該類作為超類的其他模塊的代碼的影響面殖,并且您已經(jīng)相應(yīng)地設(shè)計了類的代碼。

Guiding Principle of Access Levels 訪問級別指導(dǎo)原則

Swift中的訪問級別遵循一個總體指導(dǎo)原則:任何實體都不能根據(jù)另一個具有較低(更嚴(yán)格)訪問級別的實體來定義哭廉。

例如:

  • 不能將 public 變量定義為具有internal脊僚、file-private或private 類型,因為該類型可能在使用 public 變量的所有地方都不可用遵绰。
  • 函數(shù)的訪問級別不能高于其參數(shù)類型和返回類型辽幌,因為函數(shù)可以用于其組成類型對周圍代碼不可用的情況。

這一指導(dǎo)原則對語言不同方面的具體含義將在下面詳細(xì)介紹椿访。

Default Access Levels 默認(rèn)的訪問級別

如果您自己沒有指定顯式的訪問級別乌企,那么代碼中的所有實體(除了少數(shù)特定的例外情況,如本章后面所述)都有一個默認(rèn)的internal 訪問級別成玫。因此加酵,在許多情況下,您不需要在代碼中指定顯式的訪問級別哭当。

Access Levels for Single-Target Apps 單個target的App訪問級別

當(dāng)您編寫一個簡單的單目標(biāo)應(yīng)用程序時猪腕,應(yīng)用程序中的代碼通常是自包含在應(yīng)用程序內(nèi)的,并且不需要在應(yīng)用程序的模塊之外可用钦勘。默認(rèn)訪問級別( internal )已經(jīng)匹配此要求陋葡。因此,您不需要指定自定義訪問級別彻采。但是脖岛,您可能希望將代碼的某些部分標(biāo)記為file private或private,以便對應(yīng)用程序模塊中的其他代碼隱藏它們的實現(xiàn)細(xì)節(jié)颊亮。

Access Levels for Frameworks 框架訪問級別

當(dāng)您開發(fā)一個框架時柴梆,將該框架的面向公共的接口標(biāo)記為open或public,以便其他模塊(例如導(dǎo)入框架的應(yīng)用程序)可以查看和訪問它终惑。這個面向公共的接口是框架的應(yīng)用程序編程接口(或API)绍在。

注意:框架的任何內(nèi)部實現(xiàn)細(xì)節(jié)仍然可以使用默認(rèn)的內(nèi)部訪問級別,或者如果您想將它們隱藏在框架內(nèi)部代碼的其他部分中,可以將它們標(biāo)記為私有或文件私有偿渡。只有在希望實體成為框架API的一部分時臼寄,才需要將其標(biāo)記為open或public。

Access Levels for Unit Test Targets 單元測試target的訪問級別

當(dāng)您編寫帶有單元測試目標(biāo)的應(yīng)用程序時溜宽,應(yīng)用程序中的代碼需要對該模塊可用吉拳,以便進(jìn)行測試。默認(rèn)情況下适揉,其他模塊只能訪問標(biāo)記為open或public的實體留攒。但是,如果您使用@屬性標(biāo)記產(chǎn)品模塊的導(dǎo)入聲明嫉嘀,并在啟用測試的情況下編譯該產(chǎn)品模塊炼邀,則單元測試目標(biāo)可以訪問任何內(nèi)部實體。

Access Control Syntax 訪問控制語法

定義實體的訪問級別剪侮,方法是在實體的引入者之前放置一個open, public, internal, fileprivate, or private 修飾符:

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() {}

除非另外指定拭宁,否則默認(rèn)訪問級別是 internal,這意味著SomeInternalClass和someInternalConstant可以在沒有顯式訪問級別修飾符的情況下編寫瓣俯,并且仍然具有internal的訪問級別:

class SomeInternalClass {}              // implicitly internal
let someInternalConstant = 0            // implicitly internal

Custom Types 自定義類型

如果希望為自定義類型指定顯式訪問級別杰标,請在定義該類型時指定。然后彩匕,只要訪問級別允許在旱,就可以使用新類型。例如推掸,如果定義了文件私有類桶蝎,該類只能用作定義文件私有類的源文件中的屬性類型、函數(shù)參數(shù)或返回類型谅畅。

類型的訪問控制級別還影響該類型成員的默認(rèn)訪問級別(其屬性登渣、方法、初始化器和下標(biāo))毡泻。如果將類型的訪問級別定義為私有或文件私有胜茧,則其成員的默認(rèn)訪問級別也將是私有或文件私有。如果將類型的訪問級別定義為內(nèi)部訪問級別或公共訪問級別(或者使用內(nèi)部訪問級別的默認(rèn)訪問級別仇味,而不顯式指定訪問級別)呻顽,則類型成員的默認(rèn)訪問級別將是內(nèi)部訪問級別。

重要的:public 類型默認(rèn)擁有 internal 成員丹墨,而不是 public 成員廊遍。如果希望類型成員為公共,則必須顯式地將其標(biāo)記為公共贩挣。這一要求確保類型的面向公共的API是您選擇發(fā)布的內(nèi)容喉前,并避免將類型的內(nèi)部工作方式錯誤地表示為公共API没酣。

public class SomePublicClass {                  // explicitly public class
    public var somePublicProperty = 0            // explicitly public class member
    var someInternalProperty = 0                 // implicitly internal class member
    fileprivate func someFilePrivateMethod() {}  // explicitly file-private class member
    private func somePrivateMethod() {}          // explicitly private class member
}

class SomeInternalClass {                       // implicitly internal class
    var someInternalProperty = 0                 // implicitly internal class member
    fileprivate func someFilePrivateMethod() {}  // explicitly file-private class member
    private func somePrivateMethod() {}          // explicitly private class member
}

fileprivate class SomeFilePrivateClass {        // explicitly file-private class
    func someFilePrivateMethod() {}              // implicitly file-private class member
    private func somePrivateMethod() {}          // explicitly private class member
}

private class SomePrivateClass {                // explicitly private class
    func somePrivateMethod() {}                  // implicitly private class member
}

Tuple Types 元組類型

元組類型的訪問級別是該元組中使用的所有類型中最受限制的訪問級別。例如卵迂,如果您使用兩種不同的類型(一種具有內(nèi)部訪問裕便,另一種具有私有訪問)組合一個元組,那么該復(fù)合元組類型的訪問級別將是私有的见咒。

元組類型不像類偿衰、結(jié)構(gòu)、枚舉和函數(shù)那樣具有獨(dú)立的定義改览。當(dāng)使用元組類型時下翎,將自動推斷出該元組類型的訪問級別,并且不能顯式指定恃疯。

Function Types 函數(shù)類型

函數(shù)類型的訪問級別計算為函數(shù)參數(shù)類型和返回類型中最受限制的訪問級別。如果函數(shù)計算的訪問級別與上下文默認(rèn)值不匹配墨闲,則必須將訪問級別顯式指定為函數(shù)定義的一部分今妄。

下面的示例定義了一個名為someFunction()的全局函數(shù),但沒有為函數(shù)本身提供特定的訪問級別修飾符鸳碧。您可能期望這個函數(shù)的默認(rèn)訪問級別為“internal”盾鳞,但事實并非如此。事實上瞻离,someFunction()不會像下面這樣編譯:

func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // function implementation goes here
}

someFunction() 函數(shù)的返回類型是一個元組類型腾仅,由上面在自定義類型中定義的兩個自定義類組成。其中一個類定義為內(nèi)部類套利,另一個定義為私有類推励。因此,復(fù)合元組類型的總體訪問級別是私有的(元組組成類型的最小訪問級別)肉迫。

因為函數(shù)的返回類型是私有的验辞,所以必須用私有修飾符標(biāo)記函數(shù)的整體訪問級別,這樣函數(shù)聲明才有效:

private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// function implementation goes here
}

使用 public 或者 iternal 修飾符標(biāo)記someFunction()的定義喊衫,或者使用默認(rèn)訪問跌造,都是無效的,因為函數(shù)的公共或內(nèi)部用戶可能沒有適當(dāng)?shù)脑L問函數(shù)返回類型中使用的私有類的權(quán)限族购。

Enumeration Types 枚舉類型

枚舉的各個用例自動接收與其所屬枚舉相同的訪問級別壳贪。不能為個別枚舉用例指定不同的訪問級別。

在下面的示例中寝杖,CompassPoint枚舉具有顯式的public訪問級別违施。因此,北瑟幕、南醉拓、東和西的枚舉案例也具有公共訪問級別:

public enum CompassPoint {
    case north
    case south
    case east
    case west
}
原始值和關(guān)聯(lián)值

枚舉定義中用于任何原始值或關(guān)聯(lián)值的類型的訪問級別必須至少與枚舉的訪問級別相同高伟姐。例如,不能使用私有類型作為具有內(nèi)部訪問級別的枚舉的raw-value類型亿卤。

Nested Types 嵌套類型

在private 類型中定義的嵌套類型具有私有的自動訪問級別愤兵。
在file-private類型中定義的嵌套類型具有文件私有的自動訪問級別。
在公共類型或內(nèi)部類型中的嵌套類型具有內(nèi)部的自動訪問級別排吴。如果希望公共類型中的嵌套類型公開可用秆乳,則必須顯式地將嵌套類型聲明為public。

Subclassing 子類化

您可以將當(dāng)前訪問上下文中可訪問的任何類子類化钻哩。
子類不能具有比超類更高的訪問級別——例如屹堰,不能給 internal 超類編寫 public 子類。

此外街氢,您可以覆蓋在特定訪問上下文中可見的任何類成員(方法扯键、屬性、初始化器或下標(biāo))珊肃。

override 可以使繼承的類成員比其超類版本更容易訪問荣刑。在下面的示例中,類A是一個公共類伦乔,帶有一個名為someMethod()的文件私有方法厉亏。類B是a的子類,具有較低的“內(nèi)部”訪問級別烈和。盡管如此爱只,B類提供了一個覆蓋someMethod()的訪問級別為“internal”,這比someMethod()的原始實現(xiàn)要高:

public class A {
    fileprivate func someMethod() {}
}

internal class B: A {
    override internal func someMethod() {}
}

甚至一個子類成員調(diào)用訪問級別更低的超類成員也是有效的,
只要調(diào)用超類的成員發(fā)生在一個允許訪問級別上下文(也就是說,在同一個源文件作為file-private成員調(diào)用超類,或在同一個模塊中調(diào)用)作為一個內(nèi)部的超類成員:

public class A {
    fileprivate func someMethod() {}
}

internal class B: A {
    override internal func someMethod() {
        super.someMethod()
    }
}

因為超類A和子類B定義在同一個源文件中招刹,所以someMethod()的B實現(xiàn)可以調(diào)用super.someMethod()恬试。

Constants, Variables, Properties, and Subscripts 常量,變量疯暑,屬性忘渔,下標(biāo)

常量、變量或?qū)傩圆荒鼙绕漕愋透_缰儿。例如畦粮,用私有類型編寫公共屬性是無效的。類似地乖阵,下標(biāo)不能比其索引類型或返回類型更公開宣赔。

如果常量、變量瞪浸、屬性或下標(biāo)使用私有類型儒将,則常量、變量对蒲、屬性或下標(biāo)也必須標(biāo)記為私有:

private var privateInstance = SomePrivateClass()

Getters and Setters

常量钩蚊、變量贡翘、屬性和下標(biāo)的getter和setter自動接收與它們所屬的常量、變量砰逻、屬性或下標(biāo)相同的訪問級別鸣驱。

您可以為setter提供比其相應(yīng)的getter更低的訪問級別,以限制該變量蝠咆、屬性或下標(biāo)的讀寫范圍踊东。通過在var或下標(biāo)導(dǎo)入器之前編寫fileprivate(set)、private(set)或internal(set)來分配較低的訪問級別刚操。

此規(guī)則適用于存儲屬性和計算屬性闸翅。即使您沒有為存儲屬性編寫顯式的getter和setter, Swift仍然為您合成隱式的getter和setter,以提供對存儲屬性的后備存儲的訪問菊霜。使用fileprivate(set)坚冀、private(set)和internal(set)以與計算屬性中的顯式setter完全相同的方式更改這個合成setter的訪問級別。

下面的例子定義了一個名為TrackedString的結(jié)構(gòu)鉴逞,它記錄了字符串屬性被修改的次數(shù):

struct TrackedString {
    private(set) var numberOfEdits = 0
    var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
}

TrackedString結(jié)構(gòu)定義了一個名為value的存儲字符串屬性记某,其初始值為“”(一個空字符串)。該結(jié)構(gòu)還定義了一個名為numberofe的存儲整數(shù)屬性华蜒,用于跟蹤該值被修改的次數(shù)辙纬。這種修改跟蹤是由value屬性上的didSet屬性觀察者實現(xiàn)的豁遭,每當(dāng)value屬性被設(shè)置為一個新值時叭喜,didSet屬性觀察者就會增加看板的數(shù)量。

TrackedString結(jié)構(gòu)和value屬性不提供顯式的訪問級別修飾符蓖谢,因此它們都接收internal的默認(rèn)訪問級別捂蕴。然而,numberofe屬性的訪問級別用私有(set)修飾符標(biāo)記闪幽,以表明屬性的getter仍然具有內(nèi)部的默認(rèn)訪問級別啥辨,但是屬性只能從TrackedString結(jié)構(gòu)的一部分代碼中設(shè)置。這使得TrackedString能夠在內(nèi)部修改numberofe屬性盯腌,但是當(dāng)它在結(jié)構(gòu)定義之外被使用時溉知,它將以只讀的形式呈現(xiàn)。

如果你創(chuàng)建一個TrackedString實例腕够,并修改它的字符串值幾次级乍,你可以看到numberofe屬性值的更新,以匹配修改的數(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)")
// Prints "The number of edits is 3"

雖然您可以從另一個源文件中查詢numberofe屬性的當(dāng)前值帚湘,但是您不能從另一個源文件中修改該屬性玫荣。這個限制保護(hù)了TrackedString編輯跟蹤功能的實現(xiàn)細(xì)節(jié),同時仍然提供了對該功能某個方面的方便訪問大诸。

注意捅厂,如果需要贯卦,可以為getter和setter分配顯式訪問級別。下面的示例顯示了TrackedString結(jié)構(gòu)的一個版本焙贷,其中該結(jié)構(gòu)定義了一個顯式的public訪問級別撵割。結(jié)構(gòu)的成員(包括numberofe屬性)因此默認(rèn)有一個內(nèi)部訪問級別。你可以讓結(jié)構(gòu)的numberofe屬性getter是公共的盈厘,而它的屬性setter是私有的睁枕,通過結(jié)合公共和私有(set)訪問級修飾符:

public struct TrackedString {
    public private(set) var numberOfEdits = 0
    public var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
    public init() {}
}

Initializers 初始化

可以為自定義初始化器分配一個訪問級別,該訪問級別小于或等于它們初始化的類型沸手。唯一的例外是必需的初始化項(如在必需的初始化項中定義的)外遇。所需的初始化器必須具有與其所屬類相同的訪問級別。

與函數(shù)和方法參數(shù)一樣契吉,初始化器參數(shù)的類型不能比初始化器自己的訪問級別更私有跳仿。

Default Initializers 默認(rèn)初始化器

正如在缺省初始化器中所描述的,Swift自動提供一個缺省初始化器捐晶,而不為任何結(jié)構(gòu)或基類提供任何參數(shù)菲语,這些結(jié)構(gòu)或基類為其所有屬性提供缺省值,并且本身不提供至少一個初始化器惑灵。

默認(rèn)初始化器具有與其初始化的類型相同的訪問級別山上,除非該類型定義為public。對于定義為public的類型英支,默認(rèn)初始化器被認(rèn)為是內(nèi)部的佩憾。如果希望在另一個模塊中使用公共類型時使用無參數(shù)初始化器使其可初始化,則必須自己顯式地提供一個公共無參數(shù)初始化器作為類型定義的一部分干花。

Default Memberwise Initializers for Structure Types 結(jié)構(gòu)類型的默認(rèn)成員初始化器

如果結(jié)構(gòu)的任何存儲屬性是私有的妄帘,則結(jié)構(gòu)類型的默認(rèn)成員初始化器被認(rèn)為是私有的。同樣池凄,如果結(jié)構(gòu)的任何存儲屬性是file private抡驼,那么初始化器就是file private。否則肿仑,初始化器的訪問級別為internal致盟。

與上面的缺省初始化器一樣,如果希望在另一個模塊中使用成員明智的初始化器可初始化公共結(jié)構(gòu)類型尤慰,則必須自己提供一個公共成員明智的初始化器作為類型定義的一部分馏锡。

Protocols 協(xié)議

如果希望為協(xié)議類型分配顯式訪問級別,請在定義協(xié)議時指定訪問級別割择。這使您能夠創(chuàng)建只能在特定訪問上下文中采用的協(xié)議眷篇。

協(xié)議定義中的每個需求的訪問級別自動設(shè)置為與協(xié)議相同的訪問級別。您不能將協(xié)議需求設(shè)置為與其支持的協(xié)議不同的訪問級別荔泳。這將確保協(xié)議的所有要求在采用該協(xié)議的任何類型上都是可見的蕉饼。

如果定義了公共協(xié)議虐杯,則協(xié)議的要求在實現(xiàn)這些要求時需要一個公共訪問級別。這種行為與其他類型不同昧港,在其他類型中擎椰,公共類型定義意味著類型成員的內(nèi)部訪問級別。

協(xié)議繼承訪問級別

如果定義從現(xiàn)有協(xié)議繼承的新協(xié)議创肥,則新協(xié)議最多可以具有與其繼承的協(xié)議相同的訪問級別达舒。例如,您不能編寫繼承自內(nèi)部協(xié)議的公共協(xié)議叹侄。

協(xié)議組合訪問級別

類型可以遵循比類型本身訪問級別更低的協(xié)議巩搏。例如,您可以定義一個可以在其他模塊中使用的公共類型趾代,但是它與內(nèi)部協(xié)議的一致性只能在內(nèi)部協(xié)議的定義模塊中使用贯底。

類型符合特定協(xié)議的上下文是類型的訪問級別和協(xié)議的訪問級別的最小值。如果一個類型是公共的撒强,但是它所遵循的協(xié)議是內(nèi)部的禽捆,那么該類型對該協(xié)議的一致性也是內(nèi)部的。

當(dāng)您編寫或擴(kuò)展一個類型以符合協(xié)議時飘哨,您必須確保該類型對每個協(xié)議需求的實現(xiàn)至少具有與該類型對該協(xié)議的一致性相同的訪問級別胚想。例如,如果一個公共類型符合一個內(nèi)部協(xié)議芽隆,那么該類型對每個協(xié)議需求的實現(xiàn)必須至少是“內(nèi)部的”浊服。

在Swift中,就像Objective-C中一樣摆马,協(xié)議一致性是全局的——一個類型不可能在同一個程序中以兩種不同的方式遵守協(xié)議臼闻。

Extensions 擴(kuò)展訪問級別

您可以在類鸿吆、結(jié)構(gòu)或枚舉可用的任何訪問上下文中擴(kuò)展類囤采、結(jié)構(gòu)或枚舉。
擴(kuò)展中添加的任何類型成員都具有與正在擴(kuò)展的原始類型中聲明的類型成員相同的默認(rèn)訪問級別惩淳。
如果擴(kuò)展公共類型或內(nèi)部類型蕉毯,則添加的任何新類型成員都具有默認(rèn)的內(nèi)部訪問級別。
如果擴(kuò)展文件私有類型思犁,則添加的任何新類型成員都具有默認(rèn)的文件私有訪問級別代虾。
如果擴(kuò)展私有類型,則添加的任何新類型成員都具有默認(rèn)的私有訪問級別激蹲。

或者棉磨,可以使用顯式訪問級別修飾符(例如,私有擴(kuò)展)標(biāo)記擴(kuò)展学辱,為擴(kuò)展中定義的所有成員設(shè)置新的默認(rèn)訪問級別乘瓤。這個新的默認(rèn)值仍然可以在擴(kuò)展中為單個類型成員重寫环形。

如果要使用擴(kuò)展來添加協(xié)議一致性,則不能為擴(kuò)展提供顯式訪問級修飾符衙傀。相反抬吟,協(xié)議自己的訪問級別用于為擴(kuò)展內(nèi)的每個協(xié)議需求實現(xiàn)提供默認(rèn)的訪問級別。

Private Members in Extensions 擴(kuò)展中的私有成員

與它們擴(kuò)展的類统抬、結(jié)構(gòu)或枚舉位于同一個文件中的擴(kuò)展的行為就好像擴(kuò)展中的代碼是作為原始類型聲明的一部分編寫的一樣火本。因此,您可以:

  • 在原始聲明中聲明一個私有成員聪建,并從同一文件中的擴(kuò)展名訪問該成員钙畔。
  • 在一個擴(kuò)展中聲明一個私有成員,并從同一文件中的另一個擴(kuò)展中訪問該成員金麸。
  • 在擴(kuò)展中聲明私有成員刃鳄,并從同一文件中的原始聲明訪問該成員。

這種行為意味著您可以以相同的方式使用擴(kuò)展來組織代碼钱骂,無論您的類型是否具有私有實體叔锐。例如,給定以下簡單協(xié)議:

protocol SomeProtocol {
    func doSomething()
}

您可以使用擴(kuò)展來添加協(xié)議一致性见秽,如下所示:

struct SomeStruct {
    private var privateVariable = 12
}

extension SomeStruct: SomeProtocol {
    func doSomething() {
        print(privateVariable)
    }
}

Generics 泛型

泛型類型或泛型函數(shù)的訪問級別是泛型類型或函數(shù)本身的訪問級別及其類型參數(shù)上的任何類型約束的訪問級別的最小值愉烙。

Type Aliases 類型別名

出于訪問控制的目的,您定義的任何類型別名都被視為不同的類型解取。類型別名的訪問級別可以小于或等于其別名類型的訪問級別步责。例如,私有類型別名可以別名私有禀苦、文件私有蔓肯、內(nèi)部、公共或開放類型振乏,但是公共類型別名不能別名內(nèi)部蔗包、文件私有或私有類型。

注意:此規(guī)則也適用于用于滿足協(xié)議一致性的關(guān)聯(lián)類型的類型別名慧邮。

<<返回目錄

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末调限,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子误澳,更是在濱河造成了極大的恐慌耻矮,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忆谓,死亡現(xiàn)場離奇詭異裆装,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門哨免,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勾扭,“玉大人,你說我怎么就攤上這事铁瞒∶钌” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵慧耍,是天一觀的道長身辨。 經(jīng)常有香客問我,道長芍碧,這世上最難降的妖魔是什么煌珊? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮泌豆,結(jié)果婚禮上定庵,老公的妹妹穿的比我還像新娘。我一直安慰自己踪危,他們只是感情好蔬浙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贞远,像睡著了一般畴博。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蓝仲,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天俱病,我揣著相機(jī)與錄音,去河邊找鬼袱结。 笑死亮隙,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的垢夹。 我是一名探鬼主播溢吻,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼棚饵!你這毒婦竟也來了煤裙?” 一聲冷哼從身側(cè)響起掩完,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤噪漾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后且蓬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體欣硼,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年恶阴,在試婚紗的時候發(fā)現(xiàn)自己被綠了诈胜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豹障。...
    茶點(diǎn)故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖焦匈,靈堂內(nèi)的尸體忽然破棺而出血公,到底是詐尸還是另有隱情,我是刑警寧澤缓熟,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布累魔,位于F島的核電站,受9級特大地震影響够滑,放射性物質(zhì)發(fā)生泄漏垦写。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一彰触、第九天 我趴在偏房一處隱蔽的房頂上張望梯投。 院中可真熱鬧,春花似錦况毅、人聲如沸分蓖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咆疗。三九已至,卻和暖如春母债,著一層夾襖步出監(jiān)牢的瞬間午磁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工毡们, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留迅皇,地道東北人。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓衙熔,卻偏偏與公主長得像登颓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子红氯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評論 2 349

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