Swift Access Control
TODO: 以下实体指: 函数 属性 types等的概称
swift 提供了五种不同访问的级别
open&public 同一个模块或者不同模块间都可以访问,通常用来定义框架的外接口
注意: public和open不同的是,public在不同模块之间不可以继承和重写,而open允许模块外被继承和重写
Internal 默认访问级别,在同一模块源文件中可以访问任何类、成员、函数,不能在模块外访问,所以一般不需要特别显示的指定访问级别
file-private 只能在定义的文件内部访问,以及同一个文件内的extension访问,可以隐藏一些在文件内部使用的功能
private 只能在其定义的作用域内访问、以及同一个文件中的extension中访问,可以隐藏一些在作用域内使用的功能
open 是开放度最高的访问权限(限制最少),private是最低的访问权限 (限制最多)
下面介绍下几种类型的访问级别:
1、框架:一般开发框架,需要对外提供的接口定义为open或者public,在内部可以使用internal,private,fileprivate来隐藏一些实现细节
2、单元测试target的访问,默认情况下只能访问open和public,但是在导入应用程序模块的语句前使用@testable特性,然后允许测试的编译设置(Build Options -> Enable Testability)下编译模块,单元测试目标可以访问模块中所有内部级别的实体
3、元组类型: 元组的访问级别,由元组中最严格的类型来决定,不能显式的指定 例如
fileprivate var mixedTuple: (InternalStruct, PrivateClass) = (InternalStruct(), PrivateClass())
这个元组的内类是private
4、函数的访问级别不能高于它的参数类型和返回类型的访问级别,因为这样函数可以在任何地方被访问,但是它的参数类型和返回类型却不可以 例如:
class TestAccessControl: NSObject {
public func test(_ test: TestPrivate) {
}
}
private struct TestPrivate {
}
会触发error: Method cannot be declared public because its parameter uses a private type
5、枚举成员的访问级别和枚举类型相同,不能单独为枚举指定不同的访问权限
public enum CompassPoint {
case north
case south
case east
case west
}
访问权限都是public
6、子类可以继承同一模块中有访问权限的类,也可以继承不同模块中open修饰的类, 子类的访问权限不能高于super的访问权限例如:
internal class InternalStruct {
var internalProperty = 20
}
public class InternalStruct1: InternalStruct {
}
触发error: Class cannot be declared public because its superclass is internal
7、settter&getter setter的访问级别可以低于对应的getter的访问级别,可以通过internal(set), private(set)来控制写入权限指定更低的访问级别
8、designated初始化的访问级别不能高于class的访问级别
9、协议中的每个方法或属性都必须具有和该协议相同的访问级别,这样才能确保该协议的所有方法或属性对于任意遵循者都可用, 协议的继承,新协议的访问级别不能高于继承的协议类型例如:
fileprivate protocol PrivateProtocol {
func test()
}
public protocol publicProtocol: PrivateProtocol {
}
error:Public protocol cannot refine a fileprivate protocol
遵循协议的上下文是类型和协议中级别最小的那个,如果一个类型是public级别,但是他的协议是internal 那么这个类型对这个协议的实现最少是Internal界别例如:
fileprivate protocol PrivateProtocol {
func test()
}
public protocol publicProtocol {
func test()
}
private class testProtocol: publicProtocol, PrivateProtocol {
//这里的test函数最少应该是fileprivate访问级别 不然会报错:Method 'test()' must be as accessible as its enclosing type because it matches a requirement in protocol 'publicProtocol'
private func test() {
}
}
10 、extension 可以访问级别允许的情况下对类、结构体、枚举扩展