日常開發中常寫:
@property (nonatomic, copy) NSString *name;
子類能直接用 self.name、_name 嗎?@property 默認生成的實例變量是什麼訪問級別?
// Father.h
@interface Father : NSObject
@private
NSString *_name; // 顯式私有
- (void)setName:(NSString *)n;
- (NSString *)name;
- (void)print;
@end
// Father.m
@implementation Father
- (void)setName:(NSString *)n { _name = n; }
- (NSString *)name { return _name; }
- (void)print { NSLog(@"%@ ---> %@", NSStringFromClass([self class]), _name); }
@end
// ChildA.m / ChildB.m 繼承 Father
// main.m
int main() {
Father *f = [Father new];
ChildA *a = [ChildA new];
ChildB *b = [ChildB new];
[f setName:@"皇帝"];
[f print]; // Father ---> 皇帝
[a print]; // ChildA ---> (null)
[b print]; // ChildB ---> (null)
[a setName:@"太子A"];
[b setName:@"太子B"];
[f print]; // Father ---> 皇帝
[a print]; // ChildA ---> 太子A
[b print]; // ChildB ---> 太子B
}
| 調用 | 輸出 | 說明 |
|---|---|---|
| [f setName:@"皇帝"] | Father: 皇帝 | 父類實例變量賦值 |
| [a print] | ChildA: (null) | 子類實例變量獨立,未共享父類內存 |
| [a setName:@"太子A"] | ChildA: 太子A | 子類調用繼承方法,操作自己的 _name |
| [f print] | Father: 皇帝 | 父類實例變量未受影響 |
_name 編譯報錯_propertyName@private),但可通過 @synthesize name = _name; 指定self.name (調用繼承的 getter/setter) 訪問自己的 那份存儲protected 方法或屬性,明確語義@public 實例變量,破壞封裝@synthesize 與自動合成的區別,統一團隊風格Objective-C 中 私有實例變量會被繼承(內存佈局包含),但直接訪問受編譯器限制。子類通過繼承方法操作的是各自副本。這種設計兼顧了內存佈局兼容性與封裝性,是理解 OC 物件模型的關鍵。