Swift 提供了五种访问控制级别,用于控制代码中各种实体(类、方法、属性等)的可见性和可访问性。
访问控制级别概览
从最开放到最严格排序:
- open - 最开放的访问级别
- public - 公开访问级别
- internal - 内部访问级别(默认)
- fileprivate - 文件私有访问级别
- private - 最严格的私有访问级别
详细说明与示例
1. open - 最高访问级别
- 可以被模块内外任何源文件访问
- 可以被模块内外任何类继承和重写
- 主要用于框架的公开接口
// 在框架中定义
open class OpenVehicle {
open var wheels: Int = 4
open func startEngine() {
print("Engine started")
}
// open类中可以有非open成员
public func publicMethod() {
print("Public method")
}
}
// 在外部模块中使用
class MyCar: OpenVehicle {
// 可以重写open方法和属性
override open func startEngine() {
super.startEngine()
print("My car engine started")
}
// 不能重写非open成员
// override func publicMethod() {} // 编译错误
}
2. public - 公开访问级别
- 可以被模块内外任何源文件访问
- 但不能在模块外被继承或重写(除非在同一模块内)
// 在框架中定义
public class PublicVehicle {
public var wheels: Int = 4
public func startEngine() {
print("Engine started")
}
// public类中可以有internal成员
internal var internalProperty: String = "Internal"
}
// 在外部模块中使用
class MyPublicCar: PublicVehicle {
// 不能重写public方法和属性
// override public func startEngine() {} // 编译错误
// 可以访问public成员
func usePublicVehicle() {
print("This vehicle has \(wheels) wheels")
startEngine()
// 不能访问internal成员
// print(internalProperty) // 编译错误
}
}
3. internal - 内部访问级别(默认)
- 只能在定义它们的模块内部访问
- 外部模块无法访问
- 如果没有显式指定访问级别,默认为internal
// 在框架中定义
internal class InternalVehicle {
internal var wheels: Int = 4
internal func startEngine() {
print("Engine started")
}
// internal类中可以有private成员
private var secretFeature: String = "Secret"
}
// 在外部模块中使用
// 无法访问internal类
// let vehicle = InternalVehicle() // 编译错误
4. fileprivate - 文件私有访问级别
- 只能在定义它们的源文件中访问
// 在同一个文件中
fileprivate class FilePrivateVehicle {
fileprivate var wheels: Int = 4
fileprivate func startEngine() {
print("Engine started")
}
}
// 可以在同一文件中访问
let myVehicle = FilePrivateVehicle()
myVehicle.startEngine()
// 在另一个文件中
// 无法访问fileprivate类
// let anotherVehicle = FilePrivateVehicle() // 编译错误
5. private - 最严格的私有访问级别
- 只能在定义它们的封闭实体(类、结构体等)内部访问
class PrivateExample {
private var secretCode: String = "1234"
private func secretMethod() {
print("Secret method called")
}
// 可以在同一类中访问private成员
func useSecret() {
print("Secret code is \(secretCode)")
secretMethod()
}
}
// 在类外部
let example = PrivateExample()
// 无法访问private成员
// print(example.secretCode) // 编译错误
// example.secretMethod() // 编译错误
访问控制规则总结
-
实体不能定义在具有更低访问级别的实体中
- 例如,不能在一个internal类中定义public方法
-
函数的访问级别不能高于其参数类型和返回类型的访问级别
internal class InternalClass {} // 错误:函数是public的,但参数类型是internal的 // public func createInternal() -> InternalClass { return InternalClass() } // 正确 internal func createInternal() -> InternalClass { return InternalClass() } -
子类的访问级别不能高于父类
internal class BaseClass {} // 正确:子类访问级别不高于父类 internal class SubClass: BaseClass {} // 错误:子类访问级别高于父类 // public class PublicSubClass: BaseClass {} -
重写可以使访问级别更高
public class Base { internal func doSomething() {} } public class Derived: Base { // 可以提高重写方法的访问级别 public override func doSomething() {} }
实际应用场景
// 框架开发中的典型用法
open class NetworkManager {
// 公开可重写的配置方法
open func configure() {
// 默认配置
}
// 公开但不可重写的方法
public final func sendRequest() {
// 发送请求的实现
prepareRequest()
}
// 内部实现细节
internal func prepareRequest() {
// 准备请求
logRequest()
}
// 文件私有实现细节
fileprivate func logRequest() {
// 记录请求日志
debugPrint()
}
// 私有实现细节
private func debugPrint() {
// 调试输出
}
}
// 外部使用
class MyNetworkManager: NetworkManager {
// 可以重写open方法
override open func configure() {
super.configure()
// 自定义配置
}
// 不能重写final方法
// override func sendRequest() {} // 编译错误
// 不能访问internal及以下级别的方法
// override func prepareRequest() {} // 编译错误
}
与Objective-C互操作的注意事项
- 要使Swift代码在Objective-C中可用,需要:
- 继承自NSObject
- 使用
@objc或@objcMembers注解 - 访问级别至少为
internal或更高
// 可在Objective-C中使用的Swift类
@objcMembers
public class ObjectiveCCompatibleClass: NSObject {
public var publicProperty: String = "Public"
internal var internalProperty: String = "Internal" // Objective-C不可见
public func publicMethod() {
// 可在Objective-C中调用
}
internal func internalMethod() {
// 在Objective-C中不可见
}
@objc public func exposedToObjectiveC() {
// 显式标记为@objc,即使internal也可以在Objective-C中使用
}
}
这些访问控制修饰符帮助开发者创建清晰的API边界,隐藏实现细节,同时提供必要的灵活性。











网友评论