官网地址:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html#//apple_ref/doc/uid/TP40014097-CH41-ID3html
一、访问控制种类swift
swift3.0之后,访问控制主要分为五类:open、public、internal、fileprivate、private,其中open级别最高,private最低。app
访问控制 | 定义 |
open | 能够访问本身模块中源文件里面的任何实体,其余模块也能够经过引入该模块中源文件访问全部的实体,而且其余模块能够继承本模块的实体和从新本模块中实体的方法 |
public | 能够访问本身模块中源文件里面的任何实体,其余模块也能够经过引入该模块中源文件访问全部的实体,但其余模块不能够继承本模块的实体和从新本模块中实体的方法 |
internal | 能够被本身模块中代码访问其余源文件里的任何实体,可是其余模块不能访问该模块中源文件里面的实体 |
fileprivate | 文件内私有,只能在当前源文件使用 |
private | 只能在类中访问,离开了这个类或者结构体的做用域之后就没法访问 |
注:函数
模块:以独立单元构建和发布的framework或app。经过XCODE bulid出来的target就能够看作是一个独立模块。ui
源文件:一个模块里面的一个swift代码文件,一个源文件里面能够包含多个类、结构等。spa
二、语法code
总法则有两条:htm
1)不能给一个变量设置高于其类型访问权限的访问权限,好比blog
2)函数的访问权限由函数参数和返回值的权限决定,取二者权限的最小值。继承
默认权限
若是没有给一个实体指定访问权限,其默认权限为internal
权限控制的语法
public class SomePublicClass {} internal class SomeInternalClass {} fileprivate class SomeFilePrivateClass {} private class SomePrivateClass {} public var somePublicVariable = 0 internal let someInternalConstant = 0 fileprivate func someFilePrivateFunction() {} private func somePrivateFunction() {}
一个实体的权限控制也影响着该实体成员的权限:若是一个实体权限控制为private或fileprivate,那么他的成员默认访问权限为private或fileprivate;若是一个实体权限控制为internal或public,那么他的成员默认访问权限为internal。若是想让一个访问权限为public的实体的成员权限也为public,必须本身指定该成员的权限为public。
public class SomePublicClass { // explicitly public class public var somePublicProperty = 0 // explicitly public class member var someInternalProperty = 0 // implicitly internal class member fileprivate func someFilePrivateMethod() {} // explicitly file-private class member private func somePrivateMethod() {} // explicitly private class member } class SomeInternalClass { // implicitly internal class var someInternalProperty = 0 // implicitly internal class member fileprivate func someFilePrivateMethod() {} // explicitly file-private class member private func somePrivateMethod() {} // explicitly private class member } fileprivate class SomeFilePrivateClass { // explicitly file-private class func someFilePrivateMethod() {} // implicitly file-private class member private func somePrivateMethod() {} // explicitly private class member } private class SomePrivateClass { // explicitly private class func somePrivateMethod() {} // implicitly private class member }
元组的访问权限
元组的访问权限取决于他包含全部类型的权限最小值。好比一个元组包含两个类型,一个类型的权限为internal,一个类型的权限为private,那么该元组的访问权限为private。
函数的访问权限
函数的访问权限规则已经在上面说了,这里再也不赘述。直接上例子:
枚举类型的访问权限
枚举成员的访问级别继承自该枚举,不能单独为枚举中的成员单独声明不一样的访问权限
子类的访问权限
子类的访问权限不能高于父类的访问权限。好比,父类的访问权限为internal,子类的访问权限就不能为public。另外,你能够在子类里面重写父类里面的(方法,属性,构造函数,下表访问器),可是要遵照三个原则(以方法为例说明):一、能在子类中访问到父类里面的方法;二、能够给重写方法设置新的访问权限;三、新赋予的权限须要大于等于父类该方法的访问权限级别。例子以下:
常量、变量、属性、下标的访问权限
他们的访问权限不能高于对应类型的访问权限。
Getter和Setter访问权限
常量、变量、属性、下标索引的Getter和Setter的访问权限继承自他们所属成员的访问级别。你能够把Setter的访问权限设置地低于对应的Getter的权限,这样就可以控制变量、属性、下标索引的读写权限。设置Setter访问权限的方法为把fileprivate(set),private(set),internal(set)放在变量、属性、下标索引的前面
struct TrackedString { //numberOfEdits的get权限为internal,set权限为private。因此numberOfEdits只能在TrackedString里面修改 private(set) var numberOfEdits = 0 var value: String = "" { didSet { numberOfEdits += 1 } } }
若是既想对Getter进行修改,也想对Setter进行修改,能够以下设置:
public struct TrackedString { //numberOfEdits的get权限为public、set权限为private public private(set) var numberOfEdits = 0 public var value: String = "" { didSet { numberOfEdits += 1 } } public init() {} }
构造器和默认构造器的访问权限
对自定义的构造器设置访问权限的时候,不能高于他所属类的访问权限。可是对于必要构造器,他的访问权限必须跟所属类的访问权限相同。
swift为结构体、类提供了一个默认的无参初始化方法,用于给他们的全部属性赋值,但不会给出具体指。默认初始化方法的访问权限与所属类型的访问权限相同,注意当类、结构体的权限为public时,默认构造器的访问权限为internal
协议的访问权限
若是要为一个协议设置访问权限,那么要确保该协议只在设置的访问权限做用域中使用。一个类能够实现一个比本身访问权限低的协议,好比定义一个Public的类,他又实现了一个internal的协议,那么这个类的访问权限为internal(取二者的最小值)。
扩展的访问权限
扩展成员和原始类成员有一致的访问权限,好比你扩展了一个带有public权限的类,那么新加的成员应该有和原始成员同样的默认为internal的访问权限。另外,能够给扩展设置明确的访问权限(例如:private extension),扩展中成员也能够设置本身的访问权限。