第18條:盡量使用不可變對(duì)象
- 盡量把對(duì)外公布出來(lái)的屬性設(shè)為只讀,而且只在確有必要時(shí)才將屬性對(duì)外公布摆尝。
- 對(duì)象中表示各種collection的那些屬性温艇,通常情況下,提供一個(gè)readonly屬性供外界使用堕汞,該屬性將返回一個(gè)不可變的collection勺爱,而此collection則是內(nèi)部那個(gè)可變collection的一份拷貝。
- 強(qiáng)調(diào):不要在返回的對(duì)象上查詢類型以確定是否可變讯检。
例子
EOCPerson類
/* EOCPerson頭文件 */
#import <Foundation/Foundation.h>
@interface EOCPerson : NSObject
@property(nonatomic ,copy, readonly) NSString *firstName;
@property(nonatomic ,copy, readonly) NSString *lastName;
@property(nonatomic ,strong, readonly) NSSet *friends; // 不可變set
- (id)initWithFirstName:(NSString *)firstName andLastName:(NSString *)lastName;
- (void)addFriend:(EOCPerson *)person;
- (void)removeFriend:(EOCPerson *)person;
@end
#import "EOCPerson.h"
@interface EOCPerson ()
// 改為readwrite屬性
@property(nonatomic ,copy, readwrite) NSString *firstName;
@property(nonatomic ,copy, readwrite) NSString *lastName;
@end
/* EOCPerson實(shí)現(xiàn)文件 */
@implementation EOCPerson
{// 實(shí)例變量
NSMutableSet *_internalFriends; // 可變set
}
- (NSSet *)friends{
return [_internalFriends copy]; // 拷貝一份不可變的set
}
- (void)addFriend:(EOCPerson *)person{
[_internalFriends addObject:person];
}
- (void)removeFriend:(EOCPerson *)person{
[_internalFriends removeObject:person];
}
- (id)initWithFirstName:(NSString *)firstName andLastName:(NSString *)lastName{
if (self = [super init]) {
#warning 不需要再copy一份
_firstName = firstName;
_lastName = lastName;
_internalFriends = [NSMutableSet new]; // 延遲初始化
}
return self;
}
// 覆寫(xiě)description方法
- (NSString *)description{
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
@end
main函數(shù)
#import <Foundation/Foundation.h>
#import "EOCPerson.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 1.創(chuàng)建3個(gè)EOCPerson對(duì)象
EOCPerson *person = [[EOCPerson alloc] initWithFirstName:@"Bob" andLastName:@"Simth"];
NSLog(@"person = %@ %@", person.firstName, person.lastName);
EOCPerson *person2 = [[EOCPerson alloc] initWithFirstName:@"Bill" andLastName:@"Jobs"];
NSLog(@"person2 = %@ %@", person2.firstName, person2.lastName);
EOCPerson *person3 = [[EOCPerson alloc] initWithFirstName:@"Jane" andLastName:@"Galloway"];
NSLog(@"person3 = %@ %@", person3.firstName, person3.lastName);
// 2.通過(guò)addFriend:方法給person添加2個(gè)朋友(person2&person3)
[person addFriend:person2];
[person addFriend:person3];
NSLog(@"the friends of person = %@", person.friends);
}
return 0;
}
輸出結(jié)果:
要點(diǎn)
- 盡量創(chuàng)建不可變的對(duì)象邻寿。
- 若某屬性僅可于對(duì)象內(nèi)部修改蝎土,則在“class-continue分類”中將其由readonly屬性擴(kuò)展為readwrite屬性。
- 不要把可變的collection作為屬性公開(kāi)绣否,而應(yīng)提供相關(guān)方法誊涯,以此修改對(duì)象中的可變collection。