這里的教程為Swift官方教程中文版。

訪問控制


1.0 翻譯:JaceFu 校對:ChildhoodAndy

2.0 翻譯+校對:mmoaay

2.1 翻譯:Prayer 校對:shanks,2015-11-01

2.2 翻譯+校對:SketchK 2016-05-17
3.0.1, shanks,2016-11-13

本頁內(nèi)容包括:

訪問控制可以限定其他源文件或模塊中的代碼對你的代碼的訪問級別。這個(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è)單一目標(biāo)的應(yīng)用程序,我們完全可以不用顯式聲明代碼的訪問級別。

注意
為了簡單起見,對于代碼中可以設(shè)置訪問級別的特性(屬性、基本類型、函數(shù)等),在下面的章節(jié)中我們會稱之為“實(shí)體”。

模塊和源文件

Swift 中的訪問控制模型基于模塊和源文件這兩個(gè)概念。

模塊指的是獨(dú)立的代碼單元,框架或應(yīng)用程序會作為一個(gè)獨(dú)立的模塊來構(gòu)建和發(fā)布。在 Swift 中,一個(gè)模塊可以使用 import 關(guān)鍵字導(dǎo)入另外一個(gè)模塊。

在 Swift 中,Xcode 的每個(gè)目標(biāo)(例如框架或應(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)用程序或者框架。盡管我們一般會將不同的類型分別定義在不同的源文件中,但是同一個(gè)源文件也可以包含多個(gè)類型、函數(shù)之類的定義。

訪問級別

Swift 為代碼中的實(shí)體提供了五種不同的訪問級別。這些訪問級別不僅與源文件中定義的實(shí)體相關(guān),同時(shí)也與源文件所屬的模塊相關(guān)。

  • 開放訪問公開訪問可以訪問同一模塊源文件中的任何實(shí)體,在模塊外也可以通過導(dǎo)入該模塊來訪問源文件里的所有實(shí)體。通常情況下,框架中的某個(gè)接口可以被任何人使用時(shí),你可以將其設(shè)置為開放或者公開訪問。
  • 內(nèi)部訪問可以訪問同一模塊源文件中的任何實(shí)體,但是不能從模塊外訪問該模塊源文件中的實(shí)體。通常情況下,某個(gè)接口只在應(yīng)用程序或框架內(nèi)部使用時(shí),你可以將其設(shè)置為內(nèi)部訪問。
  • 文件私有訪問限制實(shí)體只能被所定義的文件內(nèi)部訪問。當(dāng)需要把這些細(xì)節(jié)被整個(gè)文件使用的時(shí)候,使用文件私有訪問隱藏了一些特定功能的實(shí)現(xiàn)細(xì)節(jié)。
  • 私有訪問限制實(shí)體只能在所定義的作用域內(nèi)使用。需要把這些細(xì)節(jié)被整個(gè)作用域使用的時(shí)候,使用文件私有訪問隱藏了一些特定功能的實(shí)現(xiàn)細(xì)節(jié)。

開放訪問為最高(限制最少)訪問級別,私有訪問為最低(限制最多)訪問級別。

開放訪問只作用于類類型和類的成員,它和公開訪問的區(qū)別如下:

  • 公開訪問或者其他更嚴(yán)訪問級別的類,只能在它們定義的模塊內(nèi)部被繼承。
  • 公開訪問或者其他更嚴(yán)訪問級別的類成員,只能在它們定義的模塊內(nèi)部的子類中重寫。
  • 開放訪問的類,可以在它們定義的模塊中被繼承,也可以在引用它們的模塊中被繼承。
  • 開放訪問的類成員,可以在它們定義的模塊中子類中重寫,也可以在引用它們的模塊中的子類重寫。
  • 把一個(gè)類標(biāo)記為開放,顯式地表明,你認(rèn)為其他模塊中的代碼使用此類作為父類,然后你已經(jīng)設(shè)計(jì)好了你的類的代碼了。

訪問級別基本原則

Swift 中的訪問級別遵循一個(gè)基本原則:不可以在某個(gè)實(shí)體中定義訪問級別更低(更嚴(yán)格)的實(shí)體。

例如:

  • 一個(gè)公開訪問級別的變量,其類型的訪問級別不能是內(nèi)部,文件私有或是私有類型的。因?yàn)闊o法保證變量的類型在使用變量的地方也具有訪問權(quán)限。
  • 函數(shù)的訪問級別不能高于它的參數(shù)類型和返回類型的訪問級別。因?yàn)檫@樣就會出現(xiàn)函數(shù)可以在任何地方被訪問,但是它的參數(shù)類型和返回類型卻不可以的情況。

關(guān)于此原則的各種情況的具體實(shí)現(xiàn),將在下面的細(xì)節(jié)中體現(xiàn)。

默認(rèn)訪問級別

如果你不為代碼中的實(shí)體顯式指定訪問級別,那么它們默認(rèn)為 internal 級別(有一些例外情況,稍后會進(jìn)行說明)。因此,在大多數(shù)情況下,我們不需要顯式指定實(shí)體的訪問級別。

單目標(biāo)應(yīng)用程序的訪問級別

當(dāng)你編寫一個(gè)單目標(biāo)應(yīng)用程序時(shí),應(yīng)用的所有功能都是為該應(yīng)用服務(wù),而不需要提供給其他應(yīng)用或者模塊使用,所以我們不需要明確設(shè)置訪問級別,使用默認(rèn)的訪問級別 internal 即可。但是,你也可以使用文件私有訪問或私有訪問級別,用于隱藏一些功能的實(shí)現(xiàn)細(xì)節(jié)。

框架的訪問級別

當(dāng)你開發(fā)框架時(shí),就需要把一些對外的接口定義為開放訪問或公開訪問級別,以便使用者導(dǎo)入該框架后可以正常使用其功能。這些被你定義為對外的接口,就是這個(gè)框架的 API。

注意
框架依然會使用默認(rèn)的內(nèi)部訪問級別,也可以指定為文件私有訪問或者私有訪問級別。當(dāng)你想把某個(gè)實(shí)體作為框架的 API 的時(shí)候,需顯式為其指定開放訪問或公開訪問級別。

單元測試目標(biāo)的訪問級別

當(dāng)你的應(yīng)用程序包含單元測試目標(biāo)時(shí),為了測試,測試模塊需要訪問應(yīng)用程序模塊中的代碼。默認(rèn)情況下只有開放訪問或公開訪問級別級別的實(shí)體才可以被其他模塊訪問。然而,如果在導(dǎo)入應(yīng)用程序模塊的語句前使用 @testable 特性,然后在允許測試的編譯設(shè)置(Build Options -> Enable Testability)下編譯這個(gè)應(yīng)用程序模塊,單元測試目標(biāo)就可以訪問應(yīng)用程序模塊中所有內(nèi)部級別的實(shí)體。

訪問控制語法

通過修飾符 openpublic,internal,fileprivateprivate 來聲明實(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)的訪問級別為內(nèi)部訪問級別,可以查閱默認(rèn)訪問級別這一節(jié)。這意味著在不使用修飾符顯式聲明訪問級別的情況下,SomeInternalClasssomeInternalConstant 仍然擁有隱式的內(nèi)部訪問級別:

class SomeInternalClass {}   // 隱式內(nèi)部訪問級別
var someInternalConstant = 0 // 隱式內(nèi)部訪問級別

自定義類型

如果想為一個(gè)自定義類型指定訪問級別,在定義類型時(shí)進(jìn)行指定即可。新類型只能在它的訪問級別限制范圍內(nèi)使用。例如,你定義了一個(gè)文件私有級別的類,那這個(gè)類就只能在定義它的源文件中使用,可以作為屬性類型、函數(shù)參數(shù)類型或者返回類型,等等。

一個(gè)類型的訪問級別也會影響到類型成員(屬性、方法、構(gòu)造器、下標(biāo))的默認(rèn)訪問級別。如果你將類型指定為私有或者文件私有級別,那么該類型的所有成員的默認(rèn)訪問級別也會變成私有或者文件私有級別。如果你將類型指定為公開或者內(nèi)部訪問級別(或者不明確指定訪問級別,而使用默認(rèn)的內(nèi)部訪問級別),那么該類型的所有成員的默認(rèn)訪問級別將是內(nèi)部訪問。

重要
上面提到,一個(gè)公開類型的所有成員的訪問級別默認(rèn)為內(nèi)部訪問級別,而不是公開級別。如果你想將某個(gè)成員指定為公開訪問級別,那么你必須顯式指定。這樣做的好處是,在你定義公共接口的時(shí)候,可以明確地選擇哪些接口是需要公開的,哪些是內(nèi)部使用的,避免不小心將內(nèi)部使用的接口公開。

public class SomePublicClass {                  // 顯式公開類
    public var somePublicProperty = 0            // 顯式公開類成員
    var someInternalProperty = 0                 // 隱式內(nèi)部類成員
    fileprivate func someFilePrivateMethod() {}  // 顯式文件私有類成員
    private func somePrivateMethod() {}          // 顯式私有類成員
}

class SomeInternalClass {                       // 隱式內(nèi)部類
    var someInternalProperty = 0                 // 隱式內(nèi)部類成員
    fileprivate func someFilePrivateMethod() {}  // 顯式文件私有類成員
    private func somePrivateMethod() {}          // 顯式私有類成員
}

fileprivate class SomeFilePrivateClass {        // 顯式文件私有類
    func someFilePrivateMethod() {}              // 隱式文件私有類成員
    private func somePrivateMethod() {}          // 顯式私有類成員
}

private class SomePrivateClass {                // 顯式私有類
    func somePrivateMethod() {}                  // 隱式私有類成員
}

元組類型

元組的訪問級別將由元組中訪問級別最嚴(yán)格的類型來決定。例如,如果你構(gòu)建了一個(gè)包含兩種不同類型的元組,其中一個(gè)類型為內(nèi)部訪問級別,另一個(gè)類型為私有訪問級別,那么這個(gè)元組的訪問級別為私有訪問級別。

注意
元組不同于類、結(jié)構(gòu)體、枚舉、函數(shù)那樣有單獨(dú)的定義。元組的訪問級別是在它被使用時(shí)自動(dòng)推斷出的,而無法明確指定。

函數(shù)類型

函數(shù)的訪問級別根據(jù)訪問級別最嚴(yán)格的參數(shù)類型或返回類型的訪問級別來決定。但是,如果這種訪問級別不符合函數(shù)定義所在環(huán)境的默認(rèn)訪問級別,那么就需要明確地指定該函數(shù)的訪問級別。

下面的例子定義了一個(gè)名為 someFunction() 的全局函數(shù),并且沒有明確地指定其訪問級別。也許你會認(rèn)為該函數(shù)應(yīng)該擁有默認(rèn)的訪問級別 internal,但事實(shí)并非如此。事實(shí)上,如果按下面這種寫法,代碼將無法通過編譯:

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ù)指定為 publicinternal,或者使用默認(rèn)的訪問級別 internal 都是錯(cuò)誤的,因?yàn)槿绻言摵瘮?shù)當(dāng)做 publicinternal 級別來使用的話,可能會無法訪問 private 級別的返回值。

枚舉類型

枚舉成員的訪問級別和該枚舉類型相同,你不能為枚舉成員單獨(dú)指定不同的訪問級別。

比如下面的例子,枚舉 CompassPoint 被明確指定為 public 級別,那么它的成員 North、SouthEast、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)的 GettersSetters 的訪問級別和它們所屬類型的訪問級別相同。

Setter 的訪問級別可以低于對應(yīng)的 Getter 的訪問級別,這樣就可以控制變量、屬性或下標(biāo)的讀寫權(quán)限。在 varsubscript 關(guān)鍵字之前,你可以通過 fileprivate(set),private(set)internal(set) 為它們的寫入權(quán)限指定更低的訪問級別。

注意
這個(gè)規(guī)則同時(shí)適用于存儲型屬性和計(jì)算型屬性。即使你不明確指定存儲型屬性的 GetterSetter,Swift 也會隱式地為其創(chuàng)建 GetterSetter,用于訪問該屬性的后備存儲。使用 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è)功能通過屬性 valuedidSet 觀察器實(shí)現(xiàn),每當(dāng)給 value 賦新值時(shí)就會調(diào)用 didSet 方法,然后將 numberOfEdits 的值加一。

結(jié)構(gòu)體 TrackedString 和它的屬性 value 均沒有顯式指定訪問級別,所以它們都擁有默認(rèn)的訪問級別 internal。但是該結(jié)構(gòu)體的 numberOfEdits 屬性使用了 private(set) 修飾符,這意味著 numberOfEdits 屬性只能在定義該結(jié)構(gòu)體的源文件中賦值。numberOfEdits 屬性的 Getter 依然是默認(rèn)的訪問級別 internal,但是 Setter 的訪問級別是 private,這表示該屬性只有在當(dāng)前的源文件中是可讀寫的,而在當(dāng)前源文件所屬的模塊中只是一個(gè)可讀的屬性。

如果你實(shí)例化 TrackedString 結(jié)構(gòu)體,并多次對 value 屬性的值進(jìn)行修改,你就會看到 numberOfEdits 的值會隨著修改次數(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 屬性的值,但是你不能對其進(jìn)行賦值。這一限制保護(hù)了該記錄功能的實(shí)現(xiàn)細(xì)節(jié),同時(shí)還提供了方便的訪問方式。

你可以在必要時(shí)為 GetterSetter 顯式指定訪問級別。下面的例子將 TrackedString 結(jié)構(gòu)體明確指定為了 public 訪問級別。結(jié)構(gòu)體的成員(包括 numberOfEdits 屬性)擁有默認(rèn)的訪問級別 internal。你可以結(jié)合 publicprivate(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)造器

默認(rèn)構(gòu)造器所述,Swift 會為結(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é)議的所有要求對于任意采納者都將可用。

注意
如果你定義了一個(gè) public 訪問級別的協(xié)議,那么該協(xié)議的所有實(shí)現(xiàn)也會是 public 訪問級別。這一點(diǎn)不同于其他類型,例如,當(dāng)類型是 public 訪問級別時(shí),其成員的訪問級別卻只是 internal。

協(xié)議繼承

如果定義了一個(gè)繼承自其他協(xié)議的新協(xié)議,那么新協(xié)議擁有的訪問級別最高也只能和被繼承協(xié)議的訪問級別相同。例如,你不能將繼承自 internal 協(xié)議的新協(xié)議定義為 public 協(xié)議。

協(xié)議一致性

一個(gè)類型可以采納比自身訪問級別低的協(xié)議。例如,你可以定義一個(gè) public 級別的類型,它可以在其他模塊中使用,同時(shí)它也可以采納一個(gè) internal 級別的協(xié)議,但是只能在該協(xié)議所在的模塊中作為符合該協(xié)議的類型使用。

采納了協(xié)議的類型的訪問級別取它本身和所采納協(xié)議兩者間最低的訪問級別。也就是說如果一個(gè)類型是 public 級別,采納的協(xié)議是 internal 級別,那么采納了這個(gè)協(xié)議后,該類型作為符合協(xié)議的類型時(shí),其訪問級別也是 internal。

如果你采納了協(xié)議,那么實(shí)現(xiàn)了協(xié)議的所有要求后,你必須確保這些實(shí)現(xiàn)的訪問級別不能低于協(xié)議的訪問級別。例如,一個(gè) public 級別的類型,采納了 internal 級別的協(xié)議,那么協(xié)議的實(shí)現(xiàn)至少也得是 internal 級別。

注意
Swift 和 Objective-C 一樣,協(xié)議的一致性是全局的,也就是說,在同一程序中,一個(gè)類型不可能用兩種不同的方式實(shí)現(xiàn)同一個(gè)協(xié)議。

擴(kuò)展

你可以在訪問級別允許的情況下對類、結(jié)構(gòu)體、枚舉進(jìn)行擴(kuò)展。擴(kuò)展成員具有和原始類型成員一致的訪問級別。例如,你擴(kuò)展了一個(gè) public 或者 internal 類型,擴(kuò)展中的成員具有默認(rèn)的 internal 訪問級別,和原始類型中的成員一致 。如果你擴(kuò)展了一個(gè) private 類型,擴(kuò)展成員則擁有默認(rèn)的 private 訪問級別。

或者,你可以明確指定擴(kuò)展的訪問級別(例如,private extension),從而給該擴(kuò)展中的所有成員指定一個(gè)新的默認(rèn)訪問級別。這個(gè)新的默認(rèn)訪問級別仍然可以被單獨(dú)指定的訪問級別所覆蓋。

通過擴(kuò)展添加協(xié)議一致性

如果你通過擴(kuò)展來采納協(xié)議,那么你就不能顯式指定該擴(kuò)展的訪問級別了。協(xié)議擁有相應(yīng)的訪問級別,并會為該擴(kuò)展中所有協(xié)議要求的實(shí)現(xiàn)提供默認(rèn)的訪問級別。

泛型

泛型類型或泛型函數(shù)的訪問級別取決于泛型類型或泛型函數(shù)本身的訪問級別,還需結(jié)合類型參數(shù)的類型約束的訪問級別,根據(jù)這些訪問級別中的最低訪問級別來確定。

類型別名

你定義的任何類型別名都會被當(dāng)作不同的類型,以便于進(jìn)行訪問控制。類型別名的訪問級別不可高于其表示的類型的訪問級別。例如,private 級別的類型別名可以作為 private,file-private,internalpublic或者open類型的別名,但是 public 級別的類型別名只能作為 public 類型的別名,不能作為 internalfile-private,或 private 類型的別名。

注意
這條規(guī)則也適用于為滿足協(xié)議一致性而將類型別名用于關(guān)聯(lián)類型的情況。

? 泛型 高級運(yùn)算符 ?
?