访问控制可以控制哪些代码你可以访问,哪些代码你不能访问。
Swift 提供了三种不同的访问级别:
Public 为最高级访问级别,Private 为最低级访问级别。
在 Swift 中,访问级别有如下使用原则:
代码中的所有实体,如果你不明确的定义其访问级别,那么它们默认为 internal 级别。
当你编写一个单目标应用程序时,该应用的所有功能都是为该应用服务,不需要提供给其他应用或者模块使用,所以我们不需要明确设置访问级别,使用默认的访问级别 internal 即可。
当你开发 Framework 时,就需要把一些实体定义为 public 级别,以便其他人导入该 Framework 后可以正常使用其功能。这些被你定义为 public 的实体,就是这个 Framework 的API。
通过修饰符 public、internal、private 来声明实体的访问级别:
public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}
类的访问级别也可以影响到类成员(属性、函数、初始化方法等)的默认访问级别。如果你将类声明为 private 类,那么该类的所有成员的默认访问级别也会成为 private 。如果你将类声明为 public 或者 internal 类型,那么该类的所有成员的访问级别是 internal 。
public class SomePublicClass { // 显示的 public 类
public var somePublicProperty = 0 // 显示的 public 类成员
var someInternalProperty = 0 // 隐式的 internal 类成员
private func somePrivateMethod() {} // 显示的 private 类成员
}
class SomeInternalClass { // 隐式的 internal 类
var someInternalProperty = 0 // 隐式的 internal 类成员
private func somePrivateMethod() {} // 显示的 private 类成员
}
private class SomePrivateClass { // 显示的 private 类
var somePrivateProperty = 0 // 隐式的 private 类成员
func somePrivateMethod() {} // 隐式的 private 类成员
}
元组的访问级别使用是所有类型的访问级别使用中最为严谨的。比如说,如果你构建一个包含两种不同类型元素的元组,其中一个元素类型的访问级别为 internal,另一个为 private 级别,那么这个元组的访问级别为 private 。也就是说元组的访问级别遵循它里面元组中最低级的访问级别。
注意:元组不同于类、结构体、枚举、函数那样有单独的定义。元组的访问级别是在它被使用时自动推导出的,而不是明确的声明。
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
// function implementation goes here
}
我们可以看到,这个函数的返回类型是一个元组,该元组中包含两个自定义的类。其中一个类的访问级别是 internal,另一个的访问级别是 private,所以根据元组访问级别的原则,该元组的访问级别是 private(元组的访问级别遵循它里面元组中最低级的访问级别)。
因为该函数返回类型的访问级别是private,所以你必须使用private修饰符,明确地申请该函数:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) { // function implementation goes here }
枚举中成员的访问级别继承自该枚举,你不能为枚举中的成员指定访问级别。
比如下面的例子,枚举 CompassPoint 被明确的声明为 public 级别,那么它的成员 North,South,East,West 的访问级别同样也是 public:
public enum CompassPoint { case North case South case East case West }
用于枚举定义中的任何原始值,或关联的值类型必须有一个访问级别,至少要高于枚举的访问级别。比如说,你不能在一个 internal 访问级别的枚举中定义 private 级别的原始值类型。
如果在private级别的类型中定义嵌套类型,那么该嵌套类型就自动拥有 private 访问级别。如果在 public 或者 internal 级别的类型中定义嵌套类型,那么该嵌套类型自动拥有 internal 访问级别。如果想让嵌套类型拥有 public 访问级别,那么需要对该嵌套类型进行明确的访问级别声明。
子类的访问级别可以比父类低,但是不能高于父类的访问级别。比如说,父类的访问级别是 internal ,子类的访问级别就不能声明为 public 。
public class A { private func someMethod() {} } internal class B: A { override internal func someMethod() { // 重写了父类的方法访问级别 super.someMethod() } }
private var privateInstance = SomePrivateClass()
常量、变量、属性、下标索引的 Getters 和 Setters 的访问级别继承自它们所属成员的访问级别。
Setter 的访问级别可以低于对应的 Getter 的访问级别,这样就可以控制变量、属性或下标索引的读写权限。在var或subscript定义作用域之前,你可以通过private(set)或internal(set)先为它门的写权限声明一个较低的访问级别。
struct TrackedString { private(set) var numberOfEdits = 0 var value: String = "" { didSet { numberOfEdits++ } } }
结构体 TrackedString 和它的属性 value 均没有明确的声明访问级别,所以它们都拥有默认的访问级别 internal。但是该结构体的 numberOfEdits 属性使用 private(set) 修饰符进行声明,这意味着numberOfEdits 属性只能在定义该结构体的源文件中赋值。numberOfEdits 属性的 Getter 依然是默认的访问级别 internal,但是 Setter 的访问级别是 private ,这表示该属性只有在当前的源文件中是可读可写的,在当前源文件所属的模块中它只是一个可读的属性。
虽然你可以在其他的源文件中实例化该结构体并且获取到numberOfEdits属性的值,但是你不能对其进行赋值。
我们可以给自定义的初始化方法指定访问级别,但是必须要低于或等于它所属类的访问级别。但如果该初始化方法是必须要使用的话,那它的访问级别就必须和所属类的访问级别相同
Swift 为结构体、类都提供了一个默认的无参初始化方法,用于给它们的所有属性提供赋值操作,但不会给出具体值。默认初始化方法的访问级别与所属类型的访问级别相同。
注意:如果一个类型被声明为public级别,那么默认的无参初始化方法的访问级别为 internal 。如果你想让无参的初始化方法在其他模块中可以被使用,那么你必须提供一个具有 public 访问级别的无参初始化方法。
如果结构体中的任一存储属性的访问级别为 private ,那么它的默认成员初始化方法访问级别就是 private 。尽管如此,结构体的默认无参初始化方法的访问级别依然是 internal 。
如果你想在其他模块中使用该结构体的默认成员初始化方法,那么你需要提供一个访问级别为 public 的默认成员初始化方法。
协议中的每一个必须要实现的函数都具有和该协议相同的访问级别。这样才能确保该协议的使用者可以实现它所提供的函数。
注意:如果你定义了一个 public 访问级别的协议,那么实现该协议提供的必要函数也会是public的访问级别。这一点不同于其他类型,比如 public 访问级别的其他类型,他们成员的访问级别为 internal 。
如果定义了一个新的协议,并且该协议继承了一个已知的协议,那么新协议拥有的访问级别最高也只和被继承协议的访问级别相同。比如说,你不能定义一个public的协议而去继承一个internal的协议。
如果你扩展了一个public类型,那么你新加的成员应该具有和原始成员一样的默认的 internal 访问级别。
当然你也可以明确声明扩展的访问级别(比如使用 private extension)给该扩展内所有成员指定一个新的默认访问级别。
如果一个扩展采用了某个协议,那么你就不能对该扩展使用访问级别修饰符来声明了。该扩展中实现协议的方法都会遵循该协议的访问级别。
泛型类型或泛型函数的访问级别遵循泛型类型、函数本身、泛型类型参数三者中访问级别最低的级别。
任何被你定义的类型别名都会被视作为不同的类型,这些类型用于访问控制。一个类型别名的访问级别可以低于或等于这个类型的访问级别。比如说,一个private级别的类型别名可以设定给一个public、internal、private的类型,但是一个public级别的类型别名只能设定给一个public级别的类型,不能设定给internal或private的类类型。
注意:这条规则也适用于为满足协议一致性而给相关类型命名别名。
2015-03-25
22:08:27
原文:http://www.cnblogs.com/huangzx/p/4367112.html