Swift 存取控制以模組為邊界,提供五個層級。本文透過實例說明各層級語意、預設行為、Getter/Setter 不對稱設定與 Framework 發布注意事項。
| 關鍵字 | 可見範圍 | 可繼承/覆寫 | 適用對象 |
|---|---|---|---|
private | 同一宣告區塊 (大括號內) | 否 | 實作細節、輔助屬性/方法 |
fileprivate | 同一原始檔 | 檔案內 | 檔案內 Extension 分組、單元測試 |
internal (預設) | 同一模組 (Target) | 模組內 | App 內部類別、Framework 內部 API |
public | 任何匯入模組者 | 否 | Framework 公開介面 (不可繼承) |
open | 任何匯入模組者 | 是 | Framework 公開介面 (可繼承/覆寫) |
public class ListItem {
// 公開屬性:任何人可讀寫
public var text: String
public var isComplete: Bool
// 公開讀、私有寫:外部可讀 UUID,只有本檔案/模組能設定
private(set) var UUID: NSUUID
// 公開初始化器:Framework 使用者可建立實例
public init(text: String, completed: Bool, UUID: NSUUID) {
self.text = text
self.isComplete = completed
self.UUID = UUID
}
// internal (預設):模組內可用,Framework 外部不可見
func refreshIdentity() {
self.UUID = NSUUID()
}
// 公開覆寫:Framework 使用者可呼叫
public override func isEqual(object: AnyObject?) -> Bool {
if let item = object as? ListItem {
return self.UUID == item.UUID
}
return false
}
}
public var readOnly: Int { get } // 唯讀 (需在 init 設定)
public private(set) var readWriteInternal: Int // 公開讀、模組內寫
public fileprivate(set) var readWriteFile: Int // 公開讀、檔案內寫
internal public(set) var internalReadPublicWrite: Int // 模組讀、公開寫 (罕用)
語法:accessLevel(setterAccessLevel) var name: Type,setter 層級**不能高於** getter。
internal。public/open 給外部使用。| 產出類型 | 生成標頭檔內容 |
|---|---|
| App Target | 包含 public + internal 宣告 |
| Framework Target | 僅包含 public/open 宣告 |
原因:Framework 標頭檔即 Objective-C 公開介面,internal 屬實作細節不應外洩。
// 擴充自有類別:可存取 private/fileprivate
extension MyClass {
private func helper() { ... } // 同檔案可見
}
// 擴充外部類別:只能存取 public/open
extension SomeFrameworkClass {
// 無法存取 fileprivate/private
public func newMethod() { ... }
}
// 條件式 Extension (Protocol 限制)
extension Array where Element: Equatable {
func firstIndex(of element: Element) -> Int? { ... }
}
private,對外暴露 public 介面。public private(set) var 或 public let。@testable import 可存取 internal,單元測試不需降低存取層級。public,需開放繼承用 open,謹慎變更現有 public 簽章。
需要外部 (其他模組) 使用?
├─ 是 → 需要被繼承/覆寫? → open
│ └─ 否 → public
└─ 否 → 需要同檔案其他類別/Extension 使用? → fileprivate
├─ 是 → 需要同模組其他檔案使用? → internal (預設)
└─ 否 → private