Swift中的访问级别有以下五种:
- open: 公开权限, 最高的权限, 可以被其他模块访问, 继承及复写。
- public: 公有访问权限,类或者类的公有属性或者公有方法可以从文件或者模块的任何地方进行访问。那么什么样才能成为一个模块呢?一个App就是一个模块,一个第三方API, 第三等方框架等都是一个完整的模块,这些模块如果要对外留有访问的属性或者方法,就应该使用public的访问权限。public的权限在Swift 3.0后无法在其他模块被复写方法/属性或被继承。
- fileprivate: 文件私有访问权限,被fileprivate修饰的类或者类的属性或方法可以在同一个物理文件中访问。如果超出该物理文件,那么有着fileprivate访问权限的类, 属性和方法就不能被访问。
- private: 私有访问权限,被private修饰的类或者类的属性或方法可以在同一个物理文件中的同一个类型(包含extension)访问。如果超出该物理文件或不属于同一类型,那么有着private访问权限的属性和方法就不能被访问。
- internal: 顾名思义,internal是内部的意思,即有着internal访问权限的属性和方法说明在模块内部可以访问,超出模块内部就不可被访问了。在Swift中默认就是internal的访问权限。
进阶篇
那是不是Swift的访问级别就是这么简单呢?当然不是,还有很多隐性条件。
- 如果一个类的访问级别是fileprivate,或private那么该类的所有成员都是fileprivate或private(此时成员无法修改访问级别),如果一个类的访问级别是open, internal或者public那么它的所有成员都是internal(如果类的访问级别是open或public,成员默认internal,此时可以单独修改成员的访问级别),类成员的访问级别不能高于类的访问级别(注意:嵌套类型的访问级别也符合此条规则);
- 常量、变量、属性、下标脚本访问级别低于其所声明的类型级别,并且如果不是默认访问级别(internal)要明确声明访问级别(例如一个常量是一个private类型的类类型,那么此常量必须声明为private);
- 在不违反1、2两条规则的情况下,setter的访问级别可以低于getter的访问级别(例如一个属性访问级别是internal,那么可以添加private(set)修饰将setter权限设置为private,在当前模块中只有此源文件可以访问,对外部是只读的);
- 必要构造方法(required修饰)的访问级别必须和类访问级别相同,结构体的默认逐一构造函数的访问级别不高于其成员的访问级别(例如一个成员是private那么这个构造函数就是private,但是可以通过自定义来声明一个public的构造函数),其他方法(包括其他构造方法和普通方法)的访问级别遵循规则1;
- 子类的访问级别不高于父类的访问级别,但是在遵循五种访问级别作用范围的前提下子类可以将父类低访问级别的成员重写成更高的访问级别(例如父类A和子类B在同一个源文件,A的访问级别是public,B的访问级别是internal,其中A有一个private方法,那么A可以覆盖其private方法并重写为internal);
- 协议中所有必须实现的成员的访问级别和协议本身的访问级别相同,其子协议的访问级别不高于父协议;
- 如果一个类继承于另一个类的同时实现了某个协议那么这个类的访问级别为父类和协议的最低访问级别,并且此类中方法访问级别和所实现的协议中的方法相同;
- 扩展的成员访问级别遵循规则1,但是对于类、结构体、枚举的扩展可以明确声明访问级别并且可以更低(例如对于internal的类,你可以声明一个private的扩展),而实现了协议的扩展的访问级别不可以明确声明;
- 元组的访问级别是元组中各个元素的最低访问级别,注意:元组的访问级别是自动推导的,无法直接使用关键字修饰其访问级别;
- 函数的访问级是函数的参数、返回值的最低级别,并且如果其访问级别和默认访问级别(internal)不符需要明确声明;
- 枚举成员的访问级别等同于枚举的访问级别(无法单独设置),同时枚举的原始值、关联值的访问级别不能低于枚举的访问级别;
- 泛型类型或泛型函数的访问级别是泛型类型、泛型函数、泛型类型参数三者中最低的一个;
- 类型别名的访问级别不能高于原类型的访问级别;
- 即使协议被声明为private, 也至少是fileprivate的级别, 因为协议不被实现就没有价值;