在物件內部盡量直接訪問實體變數
在物件內部讀取資料時,應該直接通過實體變數來讀,而寫入資料時,則應通過屬性來寫,
_name = @"Jack"不經過setter的訊息發送,直接為變數賦值,速度快,
對于以下的 name 屬性:@property (nonatomic, copy) NSString *name;
直接賦值是:_name = @"Jack"; ,通過self.name = @"Jack"其實等同于_name = @"Jack".copy,self.name = @"Jack"會觸發KVO,_name = @"Jack"不會
-self.name = @"Jack"可以在 setter 方法中進行斷點除錯,每次賦值你都知道,- 所以有一種合理折中方案就是,讀取資料的時候用
NSString *str = _name,賦值用self.name = @"Jack",
在物件內部訪問實體變數時,是通過屬性(self.proper)來訪問還是通過_proper來訪問區別在于是否執行屬性的setter、getter方法,
-
如果執行屬性的
setter、getter方法,則通過_proper來訪問, -
如果未執行屬性的
setter、getter方法,則通過屬性(self.proper)來訪問,
@interface Wrestler : NSObject
@property (copy, nonatomic) NSString *name; // 將name宣告為屬性
- (void)smell;
@end
@implementation Wrestler
@synthesize name = _name; // 屬性name可以使用實體變數_name直接訪問
- (void)setName:(NSString *)aName {
NSLog(@"Set name");
_name = [aName copy];
}
- (NSString *)name {
NSLog(@"Get name");
return [_name copy];
}
- (void)smell {
NSLog(@"*** Smelling ***");
// 使用dot syntax訪問實體變數
NSLog(@"%@", self.name);
// 直接呼叫屬性的getter方法
NSLog(@"%@", [self name]);
在初始化方法及dealloc方法中,總是應該直接通過實體變數來讀寫資料,
-
子類可能復寫
setter方法,用self.proper = @""可能不等同于_proper = @"".copy, -
我們寫一個
Wrestler的子類Cena,該類繼承了屬性name并重寫了其setter方法,該方法會先檢驗名字后綴是否為Cena,否則拋出例外,
@interface Cena : Wrestler
- (instancetype)initWithName:(NSString *)aName;
- (void)wrestle;
@end
@implementation Cena
@synthesize name = _name;
- (instancetype)initWithName:(NSString *)aName {
self = [super init];
if (self) {
NSLog(@"self.name = aName");
self.name = aName;
}
return self;
}
- (void)wrestle {
NSLog(@"I'm %@, U can't see me", self.name);
}
- (void)setName:(NSString *)aName {
if (![aName hasSuffix:@"Cena"]) {
[NSException raise:NSInvalidArgumentException format:@"last name must be Cena"];
}
_name = [aName copy];
}
@end
- 在父類Wrestler的init方法中將name初始化為空白字串@""
(instancetype)init {
self = [super init];
if (self) {
NSLog(@"self.name = empty string");
self.name = @"";
}
return self;
- 呼叫
Cena *cena = [[Cena alloc] initWithName:@"John Cena"];
[cena wrestle];
- 運行崩潰,原因:
self.name = @"";,呼叫子類中覆寫的name的setter方法,空白字串明顯沒有@"Cena"后綴,從而拋出例外,
使用Lazy Initialization配置的資料,應該通過屬性來讀取資料,
@property (strong, nonatomic) NSNumber *chamCount;
- (NSNumber *)chamCount {
if (!_chamCount) {
_chamCount = @13;
}
return _chamCount;
不要在setter/getter方法中呼叫setter/getter方法
- 將上面的setter方法修改:
- (void)setName:(NSString *)aName {
NSLog(@"Set name");
// _name = [aName copy];
self.name = aName;
}
- 運行程式,控制臺不停輸出
Set name,崩潰, - 原因:在
setter方法中呼叫setter方法會不斷嵌套呼叫,最終導致程式崩潰,getter方法同理,
要點
-
在物件內部讀取資料時,應該直接通過實體變數來讀,而寫入資料時,則應通過屬性來寫,
-
在初始化方法及dealloc方法中,總是應該直接通過實體變數來讀寫資料,
-
使用Lazy Initialization配置的資料,應該通過屬性來讀取資料,
-
不要在setter/getter方法中呼叫setter/getter方法,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/11424.html
標籤:iOS
