楼主: gsama
89 0

Swift 访问控制 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

80%

还不是VIP/贵宾

-

威望
0
论坛币
10 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
30 点
帖子
2
精华
0
在线时间
0 小时
注册时间
2018-4-20
最后登录
2018-4-20

楼主
gsama 发表于 2025-11-18 17:24:52 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

Swift 访问控制(Access Control)详解

Swift 的访问控制用于限制代码中类型、属性、方法、初始化器、下标的成员的访问权限,避免外部误用内部实现,提高封装性。

1. 访问级别概览(由高到低)

级别 关键字 说明
open
open
类和类成员可被继承和重写(仅类可用)
public
public
可被任何模块访问,可重写(但类不可继承)
internal
internal
(默认)仅当前模块内可访问
fileprivate
fileprivate
仅当前源文件内可访问
private
private
仅当前作用域(类、结构体、枚举、扩展)内可访问

模块(Module):一个独立编译单元(如 Framework、App Target)

源文件(Source File):一个

.swift
文件

2. 各访问级别详解

open
(最高)仅用于类和类成员允许其他模块继承和重写

open class Vehicle {
open func start() { print("Engine started") }
}
// 另一个模块
class Car: Vehicle {
override open func start() { print("Car started") } // 允许
}

public
可被任何模块访问类成员可被重写,但类本身不可被继承

public class Logger {
public func log(_ msg: String) { print(msg) }
}
// 外部模块
class MyLogger: Logger { } // 错误!public 类不可继承

想允许继承?用

open
internal

internal
(默认)模块内部任意访问不写关键字即为
internal

class DatabaseManager { // internal
func connect() { ... }
}

fileprivate
仅当前
.swift
文件内可访问常用于辅助方法、扩展

struct User {
fileprivate var id: Int = 0
}
extension User {
func reset() {
id = 0 // 同一文件,可访问
}
}
// 其他文件
let user = User()
user.id // 错误!fileprivate

private
仅当前作用域(类、结构体、枚举、扩展)内可访问最严格

class BankAccount {
private var balance: Double = 0
func deposit(_ amount: Double) {
balance += amount
}
}
extension BankAccount {
func info() -> String {
return "Balance: \(balance)" // 同一扩展,可访问
}
}
let account = BankAccount()
account.balance // 错误!

3. 访问控制适用范围

成员 可设置访问级别
类型(class/struct/enum) Yes
属性(var) Yes
方法(func) Yes
初始化器(init) Yes
下标(subscript) Yes
协议(protocol) Yes
扩展(extension) Yes(扩展本身无级别,继承被扩展类型的级别)

4. 关键规则(必须遵守)

规则 1:成员不能比其类型更开放

public class MyClass {
private func secret() { } // 正确
public var name: String   // 正确
}
public struct MyStruct {
fileprivate var id: Int   // 错误!fileprivate < public
}

修正:

internal var id: Int
或降低
MyStruct
internal

规则 2:函数参数和返回值不能比函数更严格

class Helper { }
public class API {
private func process(data: Helper) { } // 错误!参数比函数更严格
}

修正:

internal func process(data: Helper)

规则 3:元组类型的访问级别 = 最严格成员的级别

func getInfo() -> (String, fileprivate Struct) {
// 返回类型为 fileprivate
}

规则 4:getter/setter 可单独设置

public struct User {
private(set) var id: Int = 0        // 可读,外部不可写
public var name: String {          // 可读可写
get { _name }
}

set { _name = newValue }}

private var _name: String = ""}

let user = User()

print(user.id) // 正常

user.id = 1 // 不正确!

user.name = "Tom" // 正常

5. 扩展(Extension)中的访问管理

public class Counter {

private var value = 0

}

extension Counter {

func increment() { value += 1 } // 默认继承 Counter 的层级

fileprivate func debug() { print(value) }

}

扩展中增加的成员,访问层级可单独设定

6. 协议(Protocol)的访问管理

public protocol Loggable {

func log()

}

internal protocol Configurable { ... }

协议需求的所有成员,

至少

要与协议一样开放

public protocol JSONExportable {

func toJSON() -> String

}

struct Post: JSONExportable {

func toJSON() -> String { ... } // 至少 internal

}

7. 初始化器(init)的特别规定

默认规定:

struct

:无参数初始化器与结构体同级

class

:指定初始化器与类同级

自定义初始化器:

public struct Point {

public var x, y: Double

private init() { // 私有构造

x = 0; y = 0

}

public init(x: Double, y: Double) {

self.x = x; self.y = y

}

}

外部无法调用

Point()

,只能用

Point(x:y:)

8. 实际应用情境

情境

推荐访问层级

公开 API(如 SDK)

public

/

open

框架内部工具类

internal

辅助方法

fileprivate

敏感信息

private

只读属性

private(set)

9. 常见错误实例

// 错误 1:成员比类型更公开

public struct API {

fileprivate var token: String // 错误!

}

// 错误 2:参数比函数严格

public func login(user: private User) // 错误!

// 错误 3:协议要求未达成

public protocol Validatable {

func validate() -> Bool

}

struct Form: Validatable {

private func validate() -> Bool { true } // 错误!private < public

}

10. 最佳实践(Best Practices)

// 1. 默认采用 private / fileprivate

class NetworkManager {

private let session = URLSession.shared

private func parse<T: Decodable>(_ data: Data) -> T? { ... }

}

// 2. 公开 API 需明确标示 public

public struct APIClient {

public init() { }

public func request<T: Decodable>(_ type: T.Type) -> T? { ... }

}

// 3. 利用 private(set) 保护状态

public struct Counter {

public private(set) var count = 0

public mutating func increment() { count += 1 }

}

11. 访问控制 vs 封装

目标

方式

隐藏实现细节

private

/

fileprivate

阻止继承

final

+

private

控制读写权限

private(set)

模块隔离

internal

面试常见题

open

public

的区别?

open

允许继承和覆盖,

public

仅允许覆盖。

为什么

private

成员在扩展中仍可访问?

→ 扩展与原类型处于

相同的作用域

如何使结构体仅能通过工厂方法创建?

public struct User {

private init() { }

public static func create() -> User { User() }

}

总结:访问控制金字塔

open      ← 仅类,允许继承重写
public    ← 跨模块访问
internal  ← 模块内(默认)
fileprivate ← 文件内
private   ← 作用域内(最严)
需要 访问管理 + 组件化设计实践 ?例如: 构建一个
CoreKit
结构 设计
public API
与内部细节隔离 利用
private
避免误操作 欢迎进一步提问!
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:SWIFT Extension increment Practices Framework

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
扫码
拉您进交流群
GMT+8, 2026-2-11 02:46