swift簡單總結(三十四)—— 訪問控制

版本記錄

版本號 時間
V1.0 2017.08.01

前言

我是swift2.0的時候開始接觸的,記得那時候還不是很穩定,公司的項目也都是用oc做的,并不對swift很重視,我自己學了一段時間,到現在swift3.0+已經出來了,自己平時也不寫,忘記的也差不多了,正好項目這段時間已經上線了,不是很忙,我就可以每天總結一點了,希望對自己對大家有所幫助。在總結的時候我會對比oc進行說明,有代碼的我會給出相關比對代碼。
1. swift簡單總結(一)—— 數據簡單值和類型轉換
2. swift簡單總結(二)—— 簡單值和控制流
3. swift簡單總結(三)—— 循環控制和函數
4. swift簡單總結(四)—— 函數和類
5. swift簡單總結(五)—— 枚舉和結構體
6. swift簡單總結(六)—— 協議擴展與泛型
7. swift簡單總結(七)—— 數據類型
8. swift簡單總結(八)—— 別名、布爾值與元組
9. swift簡單總結(九)—— 可選值和斷言
10. swift簡單總結(十)—— 運算符
11. swift簡單總結(十一)—— 字符串和字符
12. swift簡單總結(十二)—— 集合類型之數組
13. swift簡單總結(十三)—— 集合類型之字典
14. swift簡單總結(十四)—— 控制流
15. swift簡單總結(十五)—— 控制轉移語句
16. swift簡單總結(十六)—— 函數
17. swift簡單總結(十七)—— 閉包(Closures)
18. swift簡單總結(十八)—— 枚舉
19. swift簡單總結(十九)—— 類和結構體
20. swift簡單總結(二十)—— 屬性
21. swift簡單總結(二十一)—— 方法
22. swift簡單總結(二十二)—— 下標腳本
23. swift簡單總結(二十三)—— 繼承
24. swift簡單總結(二十四)—— 構造過程
25. swift簡單總結(二十五)—— 構造過程
26. swift簡單總結(二十六)—— 析構過程
27. swift簡單總結(二十七)—— 自動引用計數
28. swift簡單總結(二十八)—— 可選鏈
29. swift簡單總結(二十九)—— 類型轉換
30.swift簡單總結(三十)—— 嵌套類型
31.swift簡單總結(三十一)—— 擴展
32.swift簡單總結(三十二)—— 協議
33.swift簡單總結(三十三)—— 泛型

訪問控制

訪問控制可以限定你在源文件或模塊中訪問代碼的級別,也就是說可以控制哪些代碼你可以訪問,哪些代碼你不可以訪問,這個特性可以讓我們隱藏功能實現的一些細節,并且可以明確的指定我們提供給其他人的接口中哪些部分是他們可以使用的,哪些是他們看不到的。

下面將從以下幾點進行說明

  • 模塊和源文件
  • 訪問級別
    • 訪問級別的使用原則
    • 默認訪問級別
    • 單目標應用程序的訪問級別
    • Framework的訪問級別
  • 訪問控制語法
  • 自定義類型
    • 元組類型
    • 函數類型
    • 枚舉類型
    • 原始值和關聯值
    • 嵌套類型
  • 子類
  • 常量、變量、屬性和下標
    • Getter&&Setter
  • 初始化
    • 默認初始化方法
    • 結構體的默認成員初始化方法
  • 協議
    • 協議繼承
    • 協議一致性
  • 擴展
    • 協議的擴展
  • 泛型
  • 類型別名

模塊和源文件

swift中的訪問控制模型基于模塊和源文件這兩個概念。這里,模塊指的是Frameworkapp bundle,在swift中使用import關鍵字引入自己的工程。

源文件指的是swift中的swift File,就是編寫swift代碼的文件,它屬于一個模塊,通常一個源文件包含一個類,在類中又包含函數,屬性等類型。


訪問級別

swift提供了三種不同的訪問級別,這些訪問級別相當于源文件中定義的實體,同時也相對于這些源文件所屬的模塊。

  • public:可以當問自己模塊或應用中源文件里的任何實體,別人也可以訪問引入該模塊中源文件里的所有實體。通常情況下,某個接口或Framework是可以被任何人使用時,你可以將其設置為public級別。
  • Internal :可以訪問自己模塊或應用中源文件里的任何實體,但是別人不能訪問該模塊中源文件里的實體,通常情況下,某個接口或Framework作為內部結構使用時,你可以將其設置為Internal級別。
  • Private : 只能在當前源文件中使用的實體,稱為私有實體,使用private級別,可以用作隱藏某些功能的實現細節。

public是最高訪問級別,private是最低訪問級別。

1. 訪問級別的使用原則

原則:訪問級別統一性

  • 一個public訪問級別的變量,不能將它的類型定義為Internalprivate的類型,因為變量可以被任何人訪問,但是定義它的類型不可以,所以這樣做會出現錯誤。
  • 函數的訪問級別不能高于它的參數、返回類型的訪問級別。因為如果函數定義為public而參數或者返回類型定義為Internalprivate,就會出現函數可以被任何人訪問,但是他的參數和返回值不可以,就會出現錯誤。

2. 默認訪問級別

代碼中的所有實體,如果你不明確的定義其訪問級別,那么它們的默認為Internal級別,在大多數情況下,我們不需要明確的設置實體的訪問級別,因為也大多數時候在開發一個App Bundle

3. 單目標應用程序的訪問級別

當你編寫一個單目標程序時,該應用的所有功能都是為該應用服務,不需要提供給其他應用或者模塊使用,使用默認的訪問級別Internal即可。

4. Framework的訪問級別

當你開發Framework時,你就需要把一些實體定義為Public級別,以便其他人導入即可正常使用,這些被定義為Public的實體,就是這個Framework的API。這里要注意:Framework的內部顯示細節依然可以使用默認的Internal級別,或者也可以定義為Private級別,只有你想將它作為API的實體,才將其定義為Public級別。


訪問控制語法

通過修飾符publicinternalprivate來聲明實體的訪問級別。

public class SomePublicClass{

}

internal class SomeInternalClass{

}

private class SomePrivateClass{

}

上面就是幾種類的訪問級別的聲明方式。

除非有特殊的說明,否則實體都使用默認的訪問級別internal

//隱式訪問級別 internal
class SomeInternalClass{
    //隱式訪問級別internal
    var someInternalConstant = 0
}

自定義類型

如果你想為一個自定義類型指定一個明確的訪問級別,你要明確一點,你要確保新類型的訪問級別和它實際的作用域相匹配。

類的訪問級別也可以影響到類成員(屬性、函數、初始化方法等)的默認訪問級別,如果你將類聲明為private類,那么該類的所有成員的默認訪問級別也會成為private。如果你將類聲明為publicinternal類,那么該類的所有成員的訪問級別是internal

注意:一個public類的所有成員的訪問級別默認為internal級別,而不是public級別,如果你想將某個成員申明為public級別,那么你必須使用修飾符明確的申明該成員。

public class SomePublicClass{           //顯示的public類
    public var somePublicProperty = 0   //顯示的public類成員
    var someInternalProperty = 0        //隱式的internal類成員
    private func somePrivateMethod(){   //顯示的private類成員
    }
}

class SomeInternalClass{                  //隱式訪問級別 internal
    var someInternalConstant = 0          //隱式訪問級別internal
    private func somePrivateMethod(){     //顯示的private類成員
    }
}

private class SomePrivateClass{         //顯式的private類
    var somePrivateProperty = 0         //隱式的private類成員
    func somePrivateMethod(){           //隱式的private類成員
    
    }
}

1. 元組類型

元組的訪問級別使用是所有類型的訪問級別使用中最為嚴謹的,比如你定義了含有兩種不同類型元素的元組,其中一個元素類型的訪問級別為internal,另一個為private級別,那么這個元組的訪問級別為private,也就是說元組的訪問級別遵循它里面元組中最低級的訪問級別。

元組不同于類、結構體、枚舉和函數那樣有單獨的定義,元組的訪問級別是它被使用時自動推導出的,而不是明確的聲明。

2. 函數類型

函數的訪問級別需要根據該函數的參數類型訪問級別、返回類型訪問級別得出。

下面看個簡單例子。

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

由于返回類型是元組,一個元素是internal,另外一個元素就是private,那么返回值類型是private,但是這里有個問題,編譯不過去,因為函數返回值級別是private,那么你必須使用private修飾符,明確的申請該函數。

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

3. 枚舉類型

枚舉中成員的訪問級別繼承自該枚舉,你不能為枚舉中的成員指定訪問級別。看下面個簡單例子。

public enum CompassPoint{
    case North
    case South
    case East
    case West
}

枚舉CompassPoint被明確的聲明為public,那么North等四個成員訪問基本也是public

4. 原始值和關聯值

用于枚舉定義中的任何原始值或關聯的值類型必須有一個訪問級別,至少要高于枚舉的訪問級別,比如說:你不能在一個internal訪問級別的枚舉中定義private級別的原始值類型。

5. 嵌套類型

  • 如果在private級別的類型中定義嵌套類型,那么該嵌套類型就自動擁有private訪問級別。
  • 如果在publicinternal級別的類型中定義嵌套類型,那么該嵌套類型自動擁有internal訪問級別。
  • 如果想讓嵌套的類型擁有public訪問級別,那么需要對該嵌套類型進行明確的訪問級別申明。

子類

子類的訪問級別不能高于父類的訪問級別。

下面看一個簡單例子。

public class A{
    func someMethod(){
    
    }
}

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

這里,類A的訪問級別是public,它包含一個函數someMethod,訪問級別是internal,類B繼承自類A,并且訪問級別申明為internal,但是在類B中重寫了類A中訪問級別為internal的方法someMethod,并重寫聲明為internal級別,通過這種方式,我們就可以訪問到某類中private級別的類成員,并且可重新聲明其訪問級別。


常量、變量、屬性、下標

常量、變量、屬性不能擁有比它們的類型更高的訪問級別,比如,你定義一個public級別的屬性,但是它的類型是private級別的,這是編譯器不允許的。

1. Getter && Setter

常量、變量、屬性和下標索引的settergetter的訪問級別繼承自他們所屬成員的訪問級別。setter的訪問級別可以低于對應getter的訪問級別,這樣就可以控制變量、屬性或下標索引的讀寫權限。

使用private(set)private(get)可以改變swift隱式創建的setter的訪問級別。

下面看一個簡單例子。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        var stringToEdit = TrackedString()
        stringToEdit.value = "1"
        stringToEdit.value = "2"
        print("number is \(stringToEdit.numberOfEdits)")
    }
}

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

下面看一下輸出結果

number is 2

這里,numberOfEdits屬性的getter依然是默認的訪問級別internalsetter的訪問級別是private,這表示該屬性只有在當前的源文件中是可讀可寫的,在當前源文件所屬模塊中它只是一個可讀的屬性。


初始化

我們可以給自定義的初始化方法指定訪問級別,但是必須要低于或等于它所屬類的訪問級別,但是,如果該初始化方法是必須要使用的話,那它的訪問級別就必須和所屬類的訪問級別相同。

如同函數或方法參數,初始化方法參數訪問級別也不能低于初始化方法的訪問級別。

1. 默認初始化方法

swift為結構體和類都提供了一個默認的無參初始化方法,用于給它們的所有屬性提供賦值操作,但不會給出具體值,默認初始化方法的訪問級別與所屬類型的訪問級別相同。

注意:如果一個類型被聲明為public級別,那么默認的初始化方法的訪問級別為internal,如果你想讓無參的初始化方法在其他模塊中可以被使用,那么你必須提供一個具有public訪問級別的無參初始化方法。

2. 結構體的默認成員初始化方法

如果結構體的任意存儲屬性的訪問級別為private,那么它的默認成員初始化方法的訪問級別就是private,盡管如此,結構體的初始化方法的訪問級別依然是internal。如果你想要在其他模塊中使用該結構體的默認成員初始化方法,那么你需要提供一個訪問級別為public的默認成員初始化方法。


協議

如果你想為一個協議明確的申明訪問級別,那么你就要確保該協議只在你申明的訪問級別作用域中使用。協議中的每一個必要實現的函數都具有該協議相同的訪問級別,這樣才能確保該協議的使用者可以實現它所提供的函數。

如果你定義了一個public訪問級別的協議,那么實現該協議提供的必要函數也會是public的訪問級別,這一點不用于其他類型。

1. 協議繼承

如果你定義一個新的協議,并且該協議繼承了一個已知的協議,那么新的協議擁有的訪問級別最高也只和被繼承協議的訪問級別相同,比如說:你不能定義一個public的協議去繼承一個internal的協議。

2. 協議一致性

類可以采用比自身訪問級別低的協議。采用了協議的類的訪問級別遵循它本身和采用協議中最低的訪問級別,也就是說如果一個類是public級別,采用的協議是internal級別,那么采用這個協議后,該類的訪問級別也是internal

如果你采用了協議,那么實現了協議必須的方法后,該方法的訪問級別遵循協議的訪問級別,比如說,一個public級別的類,采用了internal級別的協議,那么該類實現協議的方法至少也得是internal


擴展

擴展成員應該具有和原始類成員一致的訪問級別。你也可以明確申明擴展的訪問級別給該擴展內所有成員指定一個新的默認訪問級別,這個默認的訪問級別仍然可以被單獨成員所指定的訪問級別所覆蓋。

1. 協議的擴展

如果一個擴展采用了某個協議,那么你就不能對該擴展使用訪問級別修飾符來申明了,該擴展中實現協議的方法都會遵守該協議的訪問級別。


泛型

泛型類型或泛型函數的訪問級別遵循泛型類型、函數本身、泛型類型參數三者之間訪問級別最低的級別。


類型別名

任何被定義的類型別名都會被視作不同的類型,這些類型用于訪問控制,一個類型別名的訪問級別可以低于或等于這個類型的訪問級別,比如說:一個private級別的類型別名可以設定給一個publicinternalprivate的類型,但是一個public級別的類型別名,只能設定給一個public級別的類型,不能設定給internalprivate的類型。

注意:這條規則也適用于為滿足協議一致性而給相關類型命名別名。

后記

未完,待續~~~

長城
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,268評論 2 375

推薦閱讀更多精彩內容