Swift 訪問權限 fileprivate和 open兩個屬性的原理與介紹

在swift 3中新增長了兩種訪問控制權限 fileprivate openswift

下面結合網上資料和我的理解整理一下兩個屬性的原理與介紹。markdown

fileprivate

在原有的swift中的 private其實並非真正的私有,若是一個變量定義爲private,在同一個文件中的其餘類依然是能夠訪問到的。這個場景在使用extension的時候很明顯。框架

class User {
    private var name = "private"
}

extension User{
    var accessPrivate: String {
        return name
    }
}
複製代碼

這樣帶來了兩個問題:ide

  • 當咱們標記爲private時,意爲真的私有仍是文件內可共享呢?
  • 當咱們若是意圖爲真正的私有時,必須保證這個類或者結構體在一個單獨的文件裏。不然可能同文件裏其餘的代碼訪問到。

由此,在swift 3中,新增長了一個 fileprivate來顯式的代表,這個元素的訪問權限爲文件內私有。spa

過去的private對應如今的fileprivate。如今的private則是真正的私有,離開了這個類或者結構體的做用域外面就沒法訪問。設計

因此fileprivate > private .code

open

open則是彌補public語義上的不足。 如今的pubic有兩層含義:orm

  • 這個元素能夠在其餘做用域被訪問
  • 這個元素能夠在其餘做用域被繼承或者override

繼承是一件危險的事情。尤爲對於一個framework或者module的設計者而言。在自身的module內,類或者屬性對於做者而言是清晰的,可否被繼承或者override都是可控的。可是對於使用它的人,做者有時會但願傳達出這個類或者屬性不該該被繼承或者修改。這個對應的就是 final繼承

final的問題在於在標記以後,在任何地方都不能override。而對於lib的設計者而言,但願獲得的是在module內能夠被override,在被import到其餘地方後其餘用戶使用的時候不能被override。作用域

這就是 open產生的初衷。經過open和public標記區別一個元素在其餘module中是隻能被訪問仍是能夠被override。

通俗的理解public和open就是:

public:能夠被任何人訪問,但其餘module中不能夠被override和繼承,而在本module內能夠被override和繼承。

open:能夠被任何人使用,包括override和繼承。

下面是例子:

/// ModuleA:

// 這個類在ModuleA的範圍外是不能被繼承的,只能被訪問
public class NonSubclassableParentClass {

    public func foo() {}

    // 這是錯誤的寫法,由於class已經不能被繼承,
    // 因此他的方法的訪問權限不能大於類的訪問權限
    open func bar() {}

    // final的含義保持不變
    public final func baz() {}
}

// 在ModuleA的範圍外能夠被繼承
open class SubclassableParentClass {
    // 這個屬性在ModuleA的範圍外不能被override
    public var size : Int

    // 這個方法在ModuleA的範圍外不能被override
    public func foo() {}

    // 這個方法在任何地方均可以被override
    open func bar() {}

    ///final的含義保持不變
    public final func baz() {}
}

/// final的含義保持不變
public final class FinalClass { }
複製代碼
/// ModuleB:

import ModuleA

// 這個寫法是錯誤的,編譯會失敗
// 由於NonSubclassableParentClass類訪問權限標記的是public,只能被訪問不能被繼承
class SubclassA : NonSubclassableParentClass { }

// 這樣寫法能夠經過,由於SubclassableParentClass訪問權限爲 `open`.
class SubclassB : SubclassableParentClass {

    // 這樣寫也會編譯失敗
    // 由於這個方法在SubclassableParentClass 中的權限爲public,不是`open'.
    override func foo() { }

    // 這個方法由於在SubclassableParentClass中標記爲open,因此能夠這樣寫
    // 這裏不須要再聲明爲open,由於這個類是internal的
    override func bar() { }
}

open class SubclassC : SubclassableParentClass {
    // 這種寫法會編譯失敗,由於這個類已經標記爲open
    // 這個方法override是一個open的方法,則也須要代表訪問權限
    override func bar() { } 
}

open class SubclassD : SubclassableParentClass {
    // 正確的寫法,方法也須要標記爲open
    open override func bar() { }    
}

open class SubclassE : SubclassableParentClass {
    // 也能夠顯式的指出這個方法不能在被override
    public final override func bar() { }    
}
複製代碼

總結

如今的訪問權限  由大到小 依次爲:open,public,internal(默認),fileprivate,private。

此外,internal是系統默認訪問級別,internal修飾符可寫可不寫。

internal訪問級別所修飾的屬性或方法在源代碼所在的整個模塊均可以訪問。

若是是框架或者庫代碼,則在整個框架內部均可以訪問,框架由外部代碼所引用時,則不能夠訪問。

若是是App代碼,也是在整個App代碼,也是在整個App內部能夠訪問。

相關文章
相關標籤/搜索