- Swift的访问控制是基于模块和源文件概念的。模块是一组可以被其他模块使用import关键字引入的代码组。而源文件则是模块中的一个文件。
- 访问等级:Swift提供了5个访问等级。
- open和public:允许实体在定义它的模块中任意处被访问或者是引入了该模块的其他模块的文件中被访问。open近适用于类和类成员,其与public的区别在于允许其他模块进行子类继承和重写。
- internal:允许在定义该实体的模块中被访问
- File-private:允许在定义该实体的源文件中访问。
- private:定义该实体的declaration及其扩展中被使用。
- 任何实体都不能用另一个访问级别较低(限制性更强)的实体来定义。
- Single-Target App建议使用默认的internal访问等级。
- 框架的接口部分使用open或者public访问等级以便其它模块调用该框架。
- 单元测试可以访问internal的实体,只要被标记为@testable并在编译时打开测试。
- 自定义类型:类型的访问等级也会决定其类型成员的默认访问等级。private和fileprivate类型的成员的默认访问等级也是private或fileprivate。public和internal类型成员的默认访问等级是internal。
- 元组:元组的访问等级是其元素中最严格访问等级。比如一个元组由一个private类型和一个internal类型组成,那么元组的访问等级就是private。元组的访问等级是自动推断且不能被显示声明的。
- 函数:函数的访问等级是由其参数和返回值中最严格的访问等级决定的。你需要显示声明函数的访问等级如果默认计算的访问等级不符合要求。
- 枚举:枚举类case的访问等级与枚举类本身的访问等级一致,并且不能被单独设置。原始值或者关联值的访问等级要不低于枚举类的访问的等级。
- 嵌套类型:嵌套类型的访问等级与包含它的类型一致,除非包含类型的访问等级是public,那么嵌套类型的访问等级默认为internal。
- 子类:子类的访问等级不能高于父类。你可以重写同一个模块里类的所有类成员。你也可以重写定义在其他模块中所有公开类的成员。重写可以使继承的类成员比父类的实现有更多的访问权。
- 只要对超类成员的调用发生在允许的访问级别上下文中,子类成员调用访问权限低于子类成员的超类成员甚至是有效的
- 常量、变量和属性无法比他们的类型更加公开。下标无法比它的索引类型或者返回类型更加公开。如果常量、变量、属性或者下标使用了私有类型,那么它也必须被标记为私有。
- Getters and Setters:默认与他们所属的常量、变量、属性或者下标的访问等级一致。setter可以被赋予比getter更低的访问等级。通过在变量或者下标前写
fileprivate(set)
, private(set)
, or internal(set)
来标识。
- 初始器:必要初始器需要保持与所在类的访问等级一样的访问等级,其他初始器可以设置为不高于所在类访问等级的访问等级。其参数不能比初始器自身的访问等级更加私有。
- 默认初始器:默认初始器默认与所在类型的访问等级一致,public类型的默认初始器访问等级默认为internal。如果您希望公共类型在另一个模块中使用时可以使用无参数初始值设定项进行初始化,则必须自己显式提供公共无参数初始值设定项作为类型定义的一部分。
- 结构体如果有存储属性是private那么默认成员初始化器的访问等级为private,结构体如果有存储属性是fileprivate那么默认成员初始化器的访问等级为fileprivate,其它情况下默认都为internal。
- 协议:协议中各要求的访问等级默认与协议的访问等级一致,且不能被人为设置。有一个例外是如果你定义协议为public,那么其要求的访问等级为internal。
- 协议继承:如果定义从现有协议继承的新协议,则新协议最多可以具有与其继承的协议相同的访问级别。例如,您不能编写继承自内部协议的公共协议。
- 类型可以遵循比类型本身访问级别更低的协议。协议满足上下文中的访问等级是类型和协议访问等级中低的那一个。
- 当您编写或扩展类型以符合协议时,必须确保该类型对每个协议要求的实现至少具有与该类型对该协议的一致性相同的访问级别。
- 扩展:您可以在类、结构或枚举可用的任何访问上下文中扩展类、结构或枚举。 扩展中添加的任何类型成员都具有与要扩展的原始类型中声明的类型成员相同的默认访问级别。 如果扩展公共或内部类型,则您添加的任何新类型成员都具有默认的内部访问级别。 如果扩展文件私有类型,则您添加的任何新类型成员都具有文件私有的默认访问级别。 如果扩展私有类型,则您添加的任何新类型成员都具有默认的私有访问级别。
- 或者,您可以使用显式访问级别修饰符(例如 private)标记扩展,以为扩展中定义的所有成员设置新的默认访问级别。 对于单个类型成员,仍然可以在扩展中覆盖这个新的默认值。
- 如果您使用扩展来添加协议一致性,则无法为扩展提供显式访问级别修饰符。 相反,协议自己的访问级别用于为扩展中的每个协议要求实现提供默认访问级别。
- 扩展中的私有成员
- 在原始声明中声明一个私有成员,并从同一文件中的扩展访问该成员。
- 在一个扩展中声明私有成员,并从同一文件中的另一扩展访问该成员。
- 在扩展中声明私有成员,并从同一文件中的原始声明访问该成员。
- 范型:泛型类型或泛型函数的访问级别是泛型类型或函数本身的访问级别以及对其类型参数的任何类型约束的访问级别中的最小值。
- 类型别名:类型别名的访问级别可以小于或等于它所别名的类型的访问级别。