我下面所說的成員,是指的類型的成員變量和成員函數(shù).
一.概述
Swift的權(quán)限控制在英語中稱為Privacy,又可以叫access control
共有五種:
-
internal
默認(rèn)權(quán)限.
在模塊內(nèi)的文件,其類定義和函數(shù)定義是互相可見的,但是模塊外是不可見的,所以它又可理解為:對(duì)模塊私有.
這一點(diǎn)和C,Objective-C不同,在C和Objective-C里面,即使在模塊內(nèi)部,如果沒有使用include或者import語句,文件間的對(duì)象就彼此不可見. -
fileprivate(比internal權(quán)限更小)
只在文件內(nèi)可見.即:2個(gè)定義在同一個(gè)文件中的類型互相之間可見,但是其他文件就不可見這兩個(gè)類型.
-
private(比fileprivate權(quán)限更小)
一個(gè)聲明為private的東東只在定義它的花括號(hào)內(nèi)可見.比如一個(gè)類型的private成員變量只在這個(gè)類型的聲明中可見
但是:一個(gè)寫在文件頂層的private的聲明,它其實(shí)是fileprivate的,這個(gè)很好理解哈
-
public(比internal權(quán)限更大)
在模塊外可見.想要這樣也不是光聲明了public就可以,它需要滿足2個(gè)條件:
- 另一個(gè)模塊B必須import這個(gè)模塊A,
- 模塊A想要B可見的內(nèi)容,如類,類的成員,必須聲明為public
這樣模塊B才可以看到模塊A中被聲明為public的東西
如果自己實(shí)現(xiàn)了一個(gè)模塊,比如package或則framework,你必須至少把其中的一個(gè)類型標(biāo)記為public,否則別的模塊就算import了你的module,也無法看到任何類型. open(比public權(quán)限更大)
如果一個(gè)模塊中的類聲明為open,則另一個(gè)模塊可以子類化這個(gè)模塊的類,可以重寫它的成員
二. 詳解
Private 和 Filepivate
-
如果父類的成員聲明為private,則子類不能看到父類的private的成員.
如果子類型想要看到父類型的private成員,可以這么做:
- 把父類型的成員為聲明從private改成fileprivate
- 把子類型和父類型寫在同一個(gè)文件中
一個(gè)類內(nèi)嵌的類型可以看到該類所有的私有成員
-
extension可以看到它所擴(kuò)展的類型的所有私有成員,前提是類型的extension和類型聲明寫在同一個(gè)文件中
例:class Dog { private var whatADogSays = "woof" } extension Dog { func speak() { print(self.whatADogSays) // ok } } -
一個(gè)變量的set和get可以有不同的訪問權(quán)限
如:private(set) var myVar意味著該變量的set是private的,但是get還是internal的public private(set) var myVar意味著該變量的get是public的,set是private的 -
Objective-C 增加了權(quán)限訪問的復(fù)雜度:
- 被標(biāo)記為@objc的東東是private,但是Objective-C依然可以看見它們.這種情況也包括了被標(biāo)記為@IBAction和@IBOutlet的對(duì)象,因?yàn)樗鼈兤鋵?shí)是隱式的@objc
- 如果實(shí)現(xiàn)了一個(gè)Objective-C 的protocol, 那些屬于protocol的成員不能被標(biāo)記成private,
- 并且,在Cocoa定義的protocol中定義的可選實(shí)現(xiàn)的方法(optional method)必須至少實(shí)現(xiàn)為internal,否則Cocoa找不到也無法調(diào)用它們.
Public 和 Open
- public定義了模塊中的公有API.一個(gè)framework就是一個(gè)模塊.
- 如果一個(gè)公用類型的初始化函數(shù)是隱式的,則其他模塊并不能創(chuàng)建這個(gè)類型的對(duì)象,該初始化函數(shù)必須被顯示聲明并標(biāo)記為public
- 一個(gè)public修飾的類.在另一個(gè)模塊中,這個(gè)類只是可見,不能被繼承;而open修飾的類可以被繼承.
- 一個(gè)open修飾的類如果有個(gè)public修飾的成員,在另一個(gè)模塊中,這個(gè)成員不能被重寫;只有open修飾的成員可以被重寫.