在swift 3中新增長了兩種訪問控制權限 fileprivate
和 open
。swift
下面結合網上資料和我的理解整理一下兩個屬性的原理與介紹。markdown
在原有的swift中的 private
其實並非真正的私有,若是一個變量定義爲private,在同一個文件中的其餘類依然是能夠訪問到的。這個場景在使用extension的時候很明顯。框架
class User {
private var name = "private"
}
extension User{
var accessPrivate: String {
return name
}
}
複製代碼
這樣帶來了兩個問題:ide
由此,在swift 3中,新增長了一個 fileprivate
來顯式的代表,這個元素的訪問權限爲文件內私有。spa
過去的private對應如今的fileprivate。如今的private則是真正的私有,離開了這個類或者結構體的做用域外面就沒法訪問。設計
因此fileprivate > private .code
open則是彌補public語義上的不足。 如今的pubic有兩層含義:orm
繼承是一件危險的事情。尤爲對於一個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內部能夠訪問。