在 Objective-C 中,成員變量(實例變量)的可見性由四個訪問控制符決定。掌握它們的差異,能幫助你設計更安全、封裝性更好的類。本文將逐一解析 @private、@public、@protected、@package 的行為,並附上記憶表格與實戰範例。
| 控制符 | 同一類別 | 同一映像 | 子類別 | 全域(外部) |
|---|---|---|---|---|
@private | ✅ 可訪問 | ❌ 不可 | ❌ 不可 | ❌ 不可 |
@package | ✅ 可訪問 | ✅ 可訪問 | ❌ 不可 | ❌ 不可 |
@protected | ✅ 可訪問 | ❌ 不可 | ✅ 可訪問 | ❌ 不可 |
@public | ✅ 可訪問 | ✅ 可訪問 | ✅ 可訪問 | ✅ 可訪問 |
標記為 @private 的實例變量,只有定義它的類別內部能夠直接存取。連子類別都無法訪問。這是實現資訊隱藏的首選。
@public 讓變量在任何地方都可見,包括外部程式碼透過 object->ivar 直接存取。雖然方便,但會破壞封裝性,**實務上極少使用**。
若不寫任何控制符,預設即為 @protected。它允許當前類別與其子類別存取,但阻擋外部與同映像的其他類別。這是平衡封裝與擴展性的常用選擇。
@package 是 Objective-C 2.0 引入的機制。所謂「同一映像」,指編譯產出的同一個 Framework 或執行檔。簡單說:
@public)。這對於框架開發者極其有用:核心資料結構在框架內部可高效直存,對外卻保持封裝。
映像 = 編譯鏈接後產出的單一二進位單元(.framework、.dylib、或主執行檔)。同一個 Xcode Target 產出的二進位檔即屬同一映像。
// FKApple.h(框架公開介面)
#import
@interface FKApple : NSObject
{
@package
double _weight; // 框架內可直接讀寫,外部不可見
}
@end
// 框架內部實現檔(同一映像)
#import "FKApple.h"
@implementation FKApple
- (void)setWeight:(double)w { _weight = w; } // ✅ 合法
- (double)weight { return _weight; } // ✅ 合法
@end
// 外部 App 專案(不同映像)
#import
int main() {
FKApple *apple = [[FKApple alloc] init];
apple->_weight = 30.4; // ❌ 編譯錯誤:'_weight' is private
return 0;
}
Objective-C 的四種訪問控制符形成了由嚴到鬆的四層防線:
@private ⊂ @package ⊂ @protected ⊂ @public
理解「映像」邊界,善用 @package,能讓框架設計更具彈性與安全性。