Swift
访问控制
本文详细介绍了 Swift 中的访问控制机制,包括五种访问级别(open, public, internal, file-private, private)的区别、使用场景以及在自定义类型、子类化、扩展中的应用。
访问控制(Access Control)限制了其他源文件和模块对你的代码的访问。这对于隐藏代码的实现细节、指定明确的接口非常重要。
访问级别 (Access Levels)
Swift 提供了五种不同的访问级别,从高到低依次为:
- open:最高访问级别。允许在定义模块之外被访问和子类化(仅限类)。
- public:允许在定义模块之外被访问,但不能被子类化(对于类)或重写(对于成员)。
- internal:默认访问级别。允许在定义模块内的任何源文件中访问,但不能在模块外访问。
- fileprivate:限制在当前源文件中访问。
- private:最低访问级别。限制在当前定义的作用域(及其扩展,如果在同一文件中)内访问。
访问控制语法
通过在实体声明前添加修饰符来指定访问级别:
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() {}自定义类型
如果定义了一个自定义类型,你可以为其指定一个显式的访问级别。
public class A {
fileprivate func someMethod() {} // 在 A 的定义文件中可见
}
internal class B {
var someProperty: Int = 0 // 默认为 internal
}
private class C {
// 这里的成员默认为 private
func someMethod() {}
}类型的访问级别会影响其成员(属性、方法、初始化器等)的默认访问级别。
- 如果类型是
public或internal,成员默认为internal。 - 如果类型是
fileprivate,成员默认为fileprivate。 - 如果类型是
private,成员默认为private。
子类化 (Subclassing)
子类的访问级别不能高于父类的访问级别。例如,你不能编写一个 public 的子类继承自一个 internal 的父类。
public class A {}
internal class B: A {} // 正确
// public class C: B {} // 错误:C (public) 的访问级别高于 B (internal)此外,子类可以重写父类的成员,并提供更高的访问级别(但不能更低)。
public class A {
fileprivate func someMethod() {}
}
internal class B: A {
override internal func someMethod() {
super.someMethod()
}
}Getter 和 Setter
你可以为 setter 指定比 getter 更低的访问级别,以限制属性的读写权限。
struct TrackedString {
// 外部只读 (internal),内部可读写 (private)
private(set) var numberOfEdits = 0
var value: String = "" {
didSet {
numberOfEdits += 1
}
}
}总结
- open/public:用于库的公共接口。
- internal:用于应用内的模块级共享(默认)。
- fileprivate:用于文件内的实现细节共享。
- private:用于完全隐藏实现细节。
- private(set):常用的模式,用于创建“外部只读,内部可写”的属性。
在 GitHub 上编辑
上次更新于