Swift 4.0:訪問級(jí)別(訪問控制)

基礎(chǔ)篇

注: 下文中所提及的類和類型為Class, Enum和Struct

Swift中的訪問級(jí)別有以下五種:

  • open: 公開權(quán)限, 最高的權(quán)限, 可以被其他模塊訪問, 繼承及復(fù)寫。
  • public: 公有訪問權(quán)限,類或者類的公有屬性或者公有方法可以從文件或者模塊的任何地方進(jìn)行訪問。那么什么樣才能成為一個(gè)模塊呢?一個(gè)App就是一個(gè)模塊,一個(gè)第三方API, 第三等方框架等都是一個(gè)完整的模塊,這些模塊如果要對(duì)外留有訪問的屬性或者方法,就應(yīng)該使用public的訪問權(quán)限。public的權(quán)限在Swift 3.0后無法在其他模塊被復(fù)寫方法/屬性或被繼承。
  • fileprivate: 文件私有訪問權(quán)限,被fileprivate修飾的類或者類的屬性或方法可以在同一個(gè)物理文件中訪問。如果超出該物理文件,那么有著fileprivate訪問權(quán)限的類, 屬性和方法就不能被訪問。
  • private: 私有訪問權(quán)限,被private修飾的類或者類的屬性或方法可以在同一個(gè)物理文件中的同一個(gè)類型(包含extension)訪問。如果超出該物理文件或不屬于同一類型,那么有著private訪問權(quán)限的屬性和方法就不能被訪問。
  • internal: 顧名思義,internal是內(nèi)部的意思,即有著internal訪問權(quán)限的屬性和方法說明在模塊內(nèi)部可以訪問,超出模塊內(nèi)部就不可被訪問了。在Swift中默認(rèn)就是internal的訪問權(quán)限。

進(jìn)階篇

那是不是Swift的訪問級(jí)別就是這么簡單呢?當(dāng)然不是,還有很多隱性條件。

  1. 如果一個(gè)類的訪問級(jí)別是fileprivate,或private那么該類的所有成員都是fileprivate或private(此時(shí)成員無法修改訪問級(jí)別),如果一個(gè)類的訪問級(jí)別是open, internal或者public那么它的所有成員都是internal(如果類的訪問級(jí)別是open或public,成員默認(rèn)internal,此時(shí)可以單獨(dú)修改成員的訪問級(jí)別),類成員的訪問級(jí)別不能高于類的訪問級(jí)別(注意:嵌套類型的訪問級(jí)別也符合此條規(guī)則);
  2. 常量、變量、屬性、下標(biāo)腳本訪問級(jí)別低于其所聲明的類型級(jí)別,并且如果不是默認(rèn)訪問級(jí)別(internal)要明確聲明訪問級(jí)別(例如一個(gè)常量是一個(gè)private類型的類類型,那么此常量必須聲明為private);
  3. 在不違反1、2兩條規(guī)則的情況下,setter的訪問級(jí)別可以低于getter的訪問級(jí)別(例如一個(gè)屬性訪問級(jí)別是internal,那么可以添加private(set)修飾將setter權(quán)限設(shè)置為private,在當(dāng)前模塊中只有此源文件可以訪問,對(duì)外部是只讀的);
  4. 必要構(gòu)造方法(required修飾)的訪問級(jí)別必須和類訪問級(jí)別相同,結(jié)構(gòu)體的默認(rèn)逐一構(gòu)造函數(shù)的訪問級(jí)別不高于其成員的訪問級(jí)別(例如一個(gè)成員是private那么這個(gè)構(gòu)造函數(shù)就是private,但是可以通過自定義來聲明一個(gè)public的構(gòu)造函數(shù)),其他方法(包括其他構(gòu)造方法和普通方法)的訪問級(jí)別遵循規(guī)則1;
  5. 子類的訪問級(jí)別不高于父類的訪問級(jí)別,但是在遵循五種訪問級(jí)別作用范圍的前提下子類可以將父類低訪問級(jí)別的成員重寫成更高的訪問級(jí)別(例如父類A和子類B在同一個(gè)源文件,A的訪問級(jí)別是public,B的訪問級(jí)別是internal,其中A有一個(gè)private方法,那么A可以覆蓋其private方法并重寫為internal);
  6. 協(xié)議中所有必須實(shí)現(xiàn)的成員的訪問級(jí)別和協(xié)議本身的訪問級(jí)別相同,其子協(xié)議的訪問級(jí)別不高于父協(xié)議;
  7. 如果一個(gè)類繼承于另一個(gè)類的同時(shí)實(shí)現(xiàn)了某個(gè)協(xié)議那么這個(gè)類的訪問級(jí)別為父類和協(xié)議的最低訪問級(jí)別,并且此類中方法訪問級(jí)別和所實(shí)現(xiàn)的協(xié)議中的方法相同;
  8. 擴(kuò)展的成員訪問級(jí)別遵循規(guī)則1,但是對(duì)于類、結(jié)構(gòu)體、枚舉的擴(kuò)展可以明確聲明訪問級(jí)別并且可以更低(例如對(duì)于internal的類,你可以聲明一個(gè)private的擴(kuò)展),而實(shí)現(xiàn)了協(xié)議的擴(kuò)展的訪問級(jí)別不可以明確聲明;
  9. 元組的訪問級(jí)別是元組中各個(gè)元素的最低訪問級(jí)別,注意:元組的訪問級(jí)別是自動(dòng)推導(dǎo)的,無法直接使用關(guān)鍵字修飾其訪問級(jí)別;
  10. 函數(shù)的訪問級(jí)是函數(shù)的參數(shù)、返回值的最低級(jí)別,并且如果其訪問級(jí)別和默認(rèn)訪問級(jí)別(internal)不符需要明確聲明;
  11. 枚舉成員的訪問級(jí)別等同于枚舉的訪問級(jí)別(無法單獨(dú)設(shè)置),同時(shí)枚舉的原始值、關(guān)聯(lián)值的訪問級(jí)別不能低于枚舉的訪問級(jí)別;
  12. 泛型類型或泛型函數(shù)的訪問級(jí)別是泛型類型、泛型函數(shù)、泛型類型參數(shù)三者中最低的一個(gè);
  13. 類型別名的訪問級(jí)別不能高于原類型的訪問級(jí)別;
  14. 即使協(xié)議被聲明為private, 也至少是fileprivate的級(jí)別, 因?yàn)閰f(xié)議不被實(shí)現(xiàn)就沒有價(jià)值;

高級(jí)篇

熟悉Objective-C的朋友都知道Objective-C沒有命名空間,為了避免類名重復(fù)蘋果官方推薦使用類名前綴,這種做法從一定程度上避免了大部分問題,但是當(dāng)你在項(xiàng)目中引入一個(gè)第三方庫而這個(gè)第三方庫引用了一個(gè)和你當(dāng)前項(xiàng)目中用到的同一個(gè)庫時(shí)就會(huì)出現(xiàn)問題。因?yàn)殪o態(tài)庫最終會(huì)編譯到同一個(gè)域,最終導(dǎo)致編譯出錯(cuò)。當(dāng)然作為一個(gè)現(xiàn)代化語言Swift一定會(huì)解決這個(gè)問題,可是如果查看Swift的官方文檔,里面關(guān)于Swift的命名空間并沒有太多詳細(xì)的說明。但是Swift的作者Chris Lattner在Twitter中回答了這個(gè)問題:

Namespacing is implicit in swift, all classes (etc) are implicitly scoped by the module (Xcode target) they are in. no class prefixes needed

Swift中是實(shí)現(xiàn)了命名空間功能的,只是這個(gè)命名空間不像C#的namespace或者Java中的package那樣需要顯式在文件中指定,而是采用模塊(Module)的概念:在同一個(gè)模塊中所有的Swift類處于同一個(gè)命名空間,它們之間不需要導(dǎo)入就可以相互訪問。很明顯Swift的這種做法是為了最大限度的簡化Swift編程。其實(shí)一個(gè)module就可以看成是一個(gè)project中的一個(gè)target,在創(chuàng)建項(xiàng)目的時(shí)候默認(rèn)就會(huì)創(chuàng)建一個(gè)target,這個(gè)target的默認(rèn)模塊名稱就是這個(gè)項(xiàng)目的名稱(可以在target的Build Settings->Product Module Name配置)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容