編寫高質(zhì)量代碼52個有效方法總結(jié)(上篇)

本篇是我閱讀《Effective Objective-C 2.0 編寫高質(zhì)量iOS與OS X代碼的52個有效方法》的摘要與總結(jié)愿险。
一橱野、熟悉Objective-C

1.了解Objective-C語言的起源

Objective-C為C語言添加了面向?qū)ο筇匦阅耄瞧涑bjective-C使用動態(tài)綁定的消息結(jié)構(gòu)谷扣,也就是說竿开,在運行時才會檢查對象類型。接收一條消息之后掸读,究竟應(yīng)執(zhí)行何種代碼串远,由運行環(huán)境而非編譯器來決定宏多。

理解C語言的核心概念有助于寫好Objective-C程序。尤其要掌握內(nèi)存模型與指針澡罚。

CoreGraphics 中的CGRect 屬于結(jié)構(gòu)體伸但,如果用OC對象,性能會受影響

2.在類的頭文件中盡量少引入其他頭文件

除非確有必要留搔,否則不要引入頭文件更胖。一般來說,應(yīng)在某個類的頭文件中使用向前聲明(forward declaring)來提及別的類隔显,并在實現(xiàn)文件中引入那些類的頭文件却妨。這樣做可以盡量降低類之間的耦合。

有時無法使用向前聲明括眠,比如要聲明某個類遵循一項協(xié)議彪标。這種情況下,盡量把“該類遵循某協(xié)議”的這條聲明移至“class-continuation”分類中掷豺。如果不行的話捞烟,就把協(xié)議單獨放在一個頭文件中,然后將其引入当船。

頭文件中若想導(dǎo)入其他的類题画,用@class

3.多用字面量語法,少用與之等價的方法

應(yīng)該使用literal語法來創(chuàng)建字符串德频,數(shù)值苍息,數(shù)組,字典抱婉。與創(chuàng)建此類對象的常規(guī)方法相比档叔,這么做更加簡明扼要。

應(yīng)該通過取下標(biāo)操作來訪問數(shù)組下標(biāo)或字典中的鍵所對應(yīng)的元素蒸绩。

用literal語法創(chuàng)建數(shù)組或字典時衙四,若值中有nil,則會拋出異常患亿。因此传蹈,務(wù)必確保值里不含nil。

比如多用NSArray *array = @[@1,@2];少用NSArray *array = [NSArray arrayWithObjects:@1,@2,nil];

一句話步藕,就是代碼能寫簡單就寫簡單

4.多用類型常量惦界,少用#define預(yù)處理指令

不要用預(yù)處理指令定義常量。這樣定義出來的常量不含類型信息咙冗,編譯器只是會在編譯前據(jù)此執(zhí)行查找與替換操作沾歪。即使有人重新定義了常量值,編譯器也不會產(chǎn)生警告信息雾消,這將導(dǎo)致應(yīng)用程序中的常量值不一致灾搏。

在實現(xiàn)文件中使用static const來定義只在編譯單元內(nèi)可見的常量挫望。由于此類常量不在全局符號表中,所以無需為其名稱加前綴狂窑。

在頭文件中使用extern來聲明全局常量媳板,并在相關(guān)實現(xiàn)文件中定義其值。這種常量要出現(xiàn)在全局符號表中泉哈,所以其名稱要加以區(qū)隔蛉幸,通常用與之相關(guān)的類名做前綴。

用法:將#define EOCAnimatedViewAnimationDuration 0.3 替換為以下

EOCAnimatedView.h

extern const NSTime IntervalEOCAnimatedViewAnimationDuration;

EOCAnimatedView.m

const NSTime IntervalEOCAnimatedViewAnimationDuration = 0.3;

注意命名

5.用枚舉表示狀態(tài)丛晦、選項奕纫、狀態(tài)碼

應(yīng)該用枚舉來表示狀態(tài)機的狀態(tài)、傳遞給方法的選項遺跡狀態(tài)碼等值采呐,給這些值起個易懂的名字若锁。

如果把傳遞給某個方法的選項表示為枚舉型搁骑,而多個選項又可同時使用斧吐,那么就將各選項值定義為2的冪,以便通過按位或者操作將其組合起來仲器。

用NS_ENUM與NS_OPTIONS宏來定義枚舉類型煤率,并指明其底層數(shù)據(jù)類型。這樣做可以確保枚舉是用開發(fā)者所選的底層數(shù)據(jù)類型實現(xiàn)出來的乏冀,而不會采用編譯器所選的類型蝶糯。

在處理枚舉類型的switch語句中不要實現(xiàn)default分支。這樣的話辆沦,加入新枚舉之后昼捍,編譯器就會提示開發(fā)者:switch語句并未處理所有的枚舉。

用法:

typedef NS_Enum(NSUInteger,EOCConnectionState){

EOCConnectionStateDisconnected,

EOCConnectionStateConnecting,

EOCConnectionStateConnected,

}

switch(_currentState){

EOCConnectionStateDisconnected:

//Handle disconnected state

break;

EOCConnectionStateConnecting:

//Handle disconnected state

break;

EOCConnectionStateConnected:

//Handle disconnected state

break;

}

1 << 2 = 0b100

0b1111 >> 3 = 0b0001

二肢扯、對象妒茬、消息、runtime

6.理解“屬性”這一概念

可以通過@property語法來定義對象中所封裝的數(shù)據(jù)蔚晨。

通過“特質(zhì)”來指定存儲數(shù)據(jù)所需的正確語義

在設(shè)置屬性所對應(yīng)的實例變量時乍钻,一定要遵從該屬性所聲明的語義。

開發(fā)iOS程序時铭腕,應(yīng)該使用nonatomic屬性银择,因為atomic屬性會嚴重影響性能。

7.在對象內(nèi)部盡量直接訪問實例變量

由于不經(jīng)過Objective-C 的“方法派發(fā)”(method dispatch,見11)步驟础拨,所以直接訪問實例變量的速度當(dāng)然比較快呆抑。在這種情況下捌袜,編譯器所生成的代碼會直接訪問保存對象實例變量的那塊內(nèi)存。

直接訪問實例變量時析孽,不會調(diào)用其“設(shè)置方法”析蝴,這就繞過了為相關(guān)屬性所定義的“內(nèi)存管理語義”。比方說绿淋,如果在ARC下直接訪問一個聲明為copy的屬性闷畸,那么并不會拷貝該屬性,只會保留新值并釋放舊值吞滞。

如果直接訪問實例變量佑菩,那么不回觸發(fā)“鍵值觀察(Key-Value Observing, KVO)”通知裁赠。這樣做是否會產(chǎn)生問題殿漠,還取決于具體的對象行為。

通過屬性來訪問有助于排查與之相關(guān)的錯誤佩捞,因為可以給“獲取方法”和/或“設(shè)置方法”中新增“斷點(breakpoint)”監(jiān)測該屬性的調(diào)用者及其訪問時機

在對象內(nèi)部讀取數(shù)據(jù)時绞幌,應(yīng)該直接通過實例變量來讀,而寫入數(shù)據(jù)時一忱,應(yīng)該通過屬性來寫莲蜘。

在初始化方法及dealloc方法中,總是應(yīng)該直接通過實例變量來讀寫數(shù)據(jù)帘营。

有時會使用惰性初始化技術(shù)配置某份數(shù)據(jù)票渠,這種情況下,需要通過屬性來讀取數(shù)據(jù)芬迄。

8.理解“對象等同性”這一概念

若想檢測對象的等同性问顷,請?zhí)峁癷sEqual:”與hash方法。

相同的對象必須具有相同的hash碼禀梳,但是兩個hash碼相同的對象卻未必相同杜窄。

不要盲目的逐個監(jiān)測每條屬性,而是應(yīng)該依照具體需求來制定檢測方案算途。

編寫hash方法時塞耕,應(yīng)該使用計算速度快而且哈希碼碰撞幾率低的算法。

對象是否相同 不能用== 要用isEqual

NSString*foo =@"badger 123";

NSString*bar = [NSStringstringWithFormat:@"badger %i",123];

BOOLequalA = (foo == bar );//< equalA = NO

BOOLequalB = [fooisEqual:bar];//< equalB = YES

BOOLequalC = [fooisEqualToString:bar];//< equalC = YES

9.以“類族模式”隱藏實現(xiàn)細節(jié)

子類應(yīng)該繼承自類族中的抽象基類郊艘。

子類應(yīng)該定義自己的數(shù)據(jù)存儲方式荷科。

子類應(yīng)當(dāng)復(fù)寫超類文檔中指明需要復(fù)寫的方法

類族模式可以把實現(xiàn)細節(jié)隱藏在一套簡單的公共接口后面。

系統(tǒng)框架中經(jīng)常使用類族纱注。

從類族的公共抽象基類中繼承子類時要當(dāng)心畏浆,若有開發(fā)文檔,則應(yīng)首先閱讀狞贱。

例如NSArray與NSMutableArray

//? YDEmployee.h

#import

typedefNS_ENUM(NSUInteger, YDEmployeeType){

YDEmployeeTypeDeveloper,

YDEmployeeTypeDesigner,

YDEmployeeTypeFinance,

};

@interfaceYDEmployee :NSObject

@property(nonatomic, copy)NSString*name;

@property(nonatomic, assign)NSUIntegersalary;

//1.定義類方法刻获,根據(jù)不同type,放回同一父類對象

+(YDEmployee*)employeeWithType:(YDEmployeeType)type;

-(void)doWork;

@end

//? YDEmployee.m

#import"YDEmployee.h"

//3.定義各自子類

@interfaceYDEmployeeDeveloper :YDEmployee

@end

@implementationYDEmployeeDeveloper

-(void)doWork

{

[selfwriteCode];

}

-(void)writeCode

{

/////

}

@end

@interfaceYDEmployeeDesigner :YDEmployee

@end

@implementationYDEmployeeDesigner

-(void)doWork

{

[selfdesighApp];

}

-(void)desighApp

{

/////

}

@end

@interfaceYDEmployeeFinance :YDEmployee

@end

@implementationYDEmployeeFinance

-(void)doWork

{

[selfmanageFinance];

}

-(void)manageFinance

{

////

}

@end

@implementationYDEmployee

//2.抽象基類沒有特殊標(biāo)識瞎嬉,一般不定義init方法也不實現(xiàn)抽象函數(shù)蝎毡,各自在子類里實現(xiàn)

+(YDEmployee*)employeeWithType:(YDEmployeeType)type

{

switch(type) {

caseYDEmployeeTypeDeveloper:

return[YDEmployeeDevelopernew];

break;

caseYDEmployeeTypeDesigner:

return[YDEmployeeDesignernew];

break;

caseYDEmployeeTypeFinance:

return[YDEmployeeFinancenew];

break;

default:

break;

}

returnnil;

}

-(void)doWork

{

//2.1拋出一個異常厚柳,避免在基類里面實現(xiàn)

NSException*e = [NSException

exceptionWithName:@"exceptionName"

reason:@"必須在子類實現(xiàn)改方法"

userInfo:nil];

@throwe;

}

@end

10.在既有類中,使用關(guān)聯(lián)對象(Associated Object)存放自定義數(shù)據(jù)

可以通過“關(guān)聯(lián)對象”機制來把兩個對象連起來沐兵。

定義關(guān)聯(lián)對象時可指定內(nèi)存管理語義别垮,用以模仿定義屬性時所采用的“擁有關(guān)系”與“非擁有關(guān)系”。

只有在其他做法不可行時才應(yīng)選用關(guān)聯(lián)對象扎谎,因為這種做法通常會引入難于查找的bug碳想。

下列方法可以管理關(guān)聯(lián)對象:

voidobjc_setAssociatedObject(idobject,void*key,idvalue, objc_AssociationPolicy policy)此方法以給定的鍵和策略為某對象設(shè)置關(guān)聯(lián)對象值。

idobjc_getAssociatedObject(idobject,void*key)此方法根據(jù)給定的鍵從某對象中獲取相應(yīng)的關(guān)聯(lián)對象值毁靶。

voidobjc_removeAssociatedObjects(idobject)此方法移除指定對象的全部關(guān)聯(lián)對象胧奔。

關(guān)聯(lián)對象類型 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 等效的@property

OBJC_ASSOCIATION_ASSIGN ? ? ? ? ? assign

_RETAIN_NONATOMIC ? ? ? ? ? ? ? ? ? ? ? ?nonatomic,retain

...

11.理解objc_msgSend的作用

消息由接受者预吆,selector及參數(shù)構(gòu)成龙填。給某對象“發(fā)送消息”也就相當(dāng)于在該對象上調(diào)用方法。

發(fā)給某對象的全部消息都要由“動態(tài)消息派發(fā)系統(tǒng)”來處理拐叉,該系統(tǒng)會查出對應(yīng)的方法岩遗,并執(zhí)行其代碼。

id returnValue = [someObject messageName:parameter];

編譯器看到消息后將其轉(zhuǎn)換為標(biāo)準的C語言函數(shù)調(diào)用巷嚣,原型是:

void objc_msgSend(id self,SEL cmd,...)

轉(zhuǎn)換后:

id returnValue = objc_msgSend(someObject,@selector(messageName:),parameter);

12.理解消息轉(zhuǎn)發(fā)機制

若對象無法響應(yīng)某個selector喘先,則進入消息轉(zhuǎn)發(fā)流程。

通過運行期的動態(tài)方法解析功能廷粒,我們可以在需要用到某個方法時再將其加入類中。

對象可以將其無法解讀的某些selector轉(zhuǎn)交給其他對象處理红且。

經(jīng)過上述兩步后坝茎,如果還是沒辦法處理selector,那就啟動完整的消息轉(zhuǎn)發(fā)機制暇番。

13.用method swizzling調(diào)試黑盒方法

在runtime中嗤放,可以向類中新增或替換selector所對應(yīng)的方法實現(xiàn)。

使用另一份實現(xiàn)來替換原有的方法實現(xiàn)壁酬,這道工序叫做method swizzling次酌,開發(fā)者常用此技術(shù)向原有視線中添加功能。

一般來說舆乔,只有調(diào)試程序的時候才需要在runtime中修改方法實現(xiàn)岳服,這種做法不宜濫用。

//獲取方法實現(xiàn)

Method originalMethod =class_getInstanceMethod([NSStringclass],@selector(lowercaseSting));

Method swappedMethod =class_getInstanceMethod([NSStringclass],@selector(uppercaseString));

//交換方法

method_exchangeImplementations(originalMethod, swappedMethod);

14.理解“類對象”的用意

每個實例都有一個指向Class對象的指針希俩,用以表明其類型吊宋,而這些Class對象則構(gòu)成了類的繼承體系。

如果對象類型無法在編譯期確定颜武,那么就應(yīng)該使用類型信息查詢方法來探知璃搜。

盡量使用類型信息查詢方法來確定對象類型拖吼,而不要直接比較類對象,因為某些對象可能實現(xiàn)了消息轉(zhuǎn)發(fā)功能这吻。

對象都有isa指針吊档,指向的是對象的元類(metaclass)

id 中也包含isa指針,id對象定義

typedef struct objc_object{

Class isa;

} *id;


三唾糯、接口與API設(shè)計

15.用前綴避免命名空間沖突

選擇與你公司籍铁、應(yīng)用程序或者二者皆有關(guān)聯(lián)之名稱作為類名的前綴,并在所有代碼中均使用這一前綴趾断。

若自己所開發(fā)的程序庫中用到了第三方庫拒名,則應(yīng)為其中的名稱加上前綴。

Apple宣稱保留使用所有兩字母前綴的權(quán)利芋酌,所以自己所選用的前綴最好是三字母的增显。

比如你的程序中引用了XYZLibrary,想要發(fā)布脐帝,那么應(yīng)該都改為YDXYZLibrary,防止直接他人引入XYZLibrary產(chǎn)生沖突

16.提供“全能初始化方法”

在類中提供一個全能初始化方法同云,并于文檔里指明。其它初始化方法均應(yīng)調(diào)用此方法堵腹。

若全能初始化方法與超類不同炸站,則需覆寫超類中對應(yīng)方法。

如果超類的初始化方法并不適用于子類疚顷,那么應(yīng)該覆寫這個超類方法旱易,并在其中拋出異常。

拋出異常方法:

@throw[NSExceptionexceptionWithName:NSInternalInconsistencyExceptionreason:@"Must use initWithDimension:instead."userInfo:nil];

17.實現(xiàn)description方法

實現(xiàn)description方法返回一個有意義的字符串腿堤,用以描述該實例阀坏。

若想在調(diào)試時打印出更詳盡的對象描述信息,則應(yīng)該實現(xiàn)debugDescription方法笆檀。

//name,age 為對象屬性

- (NSString*)description{

return [NSString stringWithFormat:@"%@ %d",_name,_age];

}

- (NSString*)debugDescription{

return [NSString stringWithFormat:@"<%@: %p,\"%@ %d\">",[self ?class],self,_name,_age];

}

18.盡量使用不可變對象

盡量創(chuàng)建不可變的對象忌堂。

若某屬性僅可于對象內(nèi)部修改,則在“class-continuation分類”中將其由readonly屬性擴展為readwrite屬性酗洒。

不要把可變的collection作為屬性公開士修,而應(yīng)提供相關(guān)方法,一次修改對象中的可變collection樱衷。

擴展例子

.h 中

@property(nonatomic,copy,readonly)NSString*someString;

//提供初始化方法

- (instancetype)initWithSomeString:(NSString*)someString;

.m中class-continuation 中

@property(nonatomic,copy,readwrite)NSString*someString;

@property(nonatomic,strong,readwrite)dispatch_queue_tsyncQueue;

.m中

//派發(fā)隊列防止發(fā)生“競爭條件”

_syncQueue=dispatch_queue_create("com.manqian.syncQueue",NULL);

- (NSString*)someString{

__blockNSString*localSomeString;

dispatch_sync(_syncQueue, ^{

localSomeString =_someString;

});

returnlocalSomeString;

}

- (void)setSomeString:(NSString*)someString

{

dispatch_barrier_async(_syncQueue, ^{

_someString= someString;

});

}

19.使用清晰而協(xié)調(diào)的命名方式

起名時應(yīng)遵從標(biāo)準的Objective-C命名規(guī)范棋嘲,這樣創(chuàng)建出來的接口更容易為開發(fā)者所理解。

方法名要言簡意賅箫老,從左至右讀起來要像個日常用語中的句子才好封字。

方法名利不要使用縮略后的類型名稱。

給方法嗎起名時的第一要務(wù)就是確保其風(fēng)格與你自己的代碼或所要集成的框架相符。

繼承至UIView的子類阔籽,類名末尾一定是View流妻,同理其他的也需要這樣

20.為私有方法名加前綴

給私有方法的名稱加上前綴,這樣可以很容易的將其通公共方法區(qū)分開笆制。

不要單用一個下劃線做私有方法的前綴绅这,因為這種做法的預(yù)留給蘋果公司用的。

建議私有方法用p_ 開頭在辆,如

- (void)p_privateMethod {

/* … */

}

21.理解Objective-C錯誤模型

只有發(fā)生了可使整個應(yīng)用程序崩潰的嚴重錯誤時证薇,才使用異常。

在錯誤不那么嚴重的情況下匆篓,可以指派委托方法來處理錯誤浑度,也可把錯誤信息放在NSError對象里,經(jīng)由輸出參數(shù)返回給調(diào)用者鸦概。

NSError ** 會轉(zhuǎn)化為 ?MSError *__autoreleasing*

意為 指向指針的指針

22.理解NSCopying協(xié)議

若想令自己所寫的對象具有拷貝功能箩张,則需實現(xiàn)NSCopying協(xié)議。

如果自定義的對象分為可變版本與不可變版本窗市,那么就要同時實現(xiàn)NSCopying與NSMutableCopying協(xié)議先慷。

復(fù)制對象時需決定采用淺拷貝還是深拷貝,一般情況下應(yīng)該盡量執(zhí)行淺拷貝咨察。

如果你所寫的對象需要深拷貝论熙,那么可考慮新增一個專門執(zhí)行深拷貝的方法。

NSCopying協(xié)議只有一個方法

- (id) copyWithZone:(NSZone *)zone ?//zone 區(qū)摄狱,每個程序只有一個“默認區(qū)”

深拷貝 會新建一個對象脓诡,原來的對象被銷毀了,深拷貝的對象不會被銷毀

淺拷貝 不會新建對象二蓝,只是新增了一個指針指向原來的對象誉券,原來的對象被銷毀,淺拷貝的東西也被銷毀

四刊愚、協(xié)議與分類

23.通過委托與數(shù)據(jù)源協(xié)議進行對象間通信

委托模式為對象提供了一套接口,使其可由此將相關(guān)事件告知其他對象踩验。

將委托對象應(yīng)該支持的接口定義成協(xié)議鸥诽,在協(xié)議中把可能需要吃力的事件定義成方法。

當(dāng)某對象需要從另外一個對象中獲取數(shù)據(jù)時箕憾,可使用委托模式牡借。在這種情況下,該模式亦稱數(shù)據(jù)源協(xié)議袭异。

若有必要钠龙,可實現(xiàn)含有位段的結(jié)構(gòu)體,將委托對象是否能響應(yīng)相關(guān)協(xié)議方法這一信息緩存至其中。

數(shù)據(jù)流向

Data Source —>class—>Delegate

#import <Foundation/Foundation>

@classYDNetworkFetcher;

@protocolYDNetworkFetcherDelegate

@optional

- (void)networkFetcher:(YDNetworkFetcher*)fetcher didReceiveData:(NSData*)data;

- (void)networkFetcher:(YDNetworkFetcher*)fetcher didFailWithError:(NSError*)error;

- (void)networkFetcher:(YDNetworkFetcher*)fetcher didUpdateProgressTo:(float*)progress;

@end?

@interfaceYDNetworkFetcher :NSObject

/***設(shè)置代理*/

@property(nonatomic,weak)id delegate;

@end

#import"YDNetworkFetcher.h"

@interfaceYDNetworkFetcher()

{

struct{

unsignedintdidReceiveData :1;

unsignedintdidFailWithError :1;

unsignedintdidUpdateProgressTo :1;

} _delegateFlags;

}

@end

@implementationYDNetworkFetcher

- (void)setDelegate:(id)delegate{

iddelegateObject = delegate;

_delegate= delegate;

//將代理是否執(zhí)行方法緩存起來

_delegateFlags.didReceiveData= [delegateObjectrespondsToSelector:@selector(networkFetcher:didReceiveData:)];

_delegateFlags.didFailWithError= [delegateObjectrespondsToSelector:@selector(networkFetcher:didFailWithError:)];

_delegateFlags.didUpdateProgressTo= [delegateObjectrespondsToSelector:@selector(networkFetcher:didUpdateProgressTo:)];

}

- (void)networkFetcher:(YDNetworkFetcher*)fetcher didReceiveData:(NSData*)data

{

//不需要每次都去查找是否實現(xiàn)該方法

if(_delegateFlags.didReceiveData) {

[_delegatenetworkFetcher:selfdidReceiveData:data];

}

}

- (void)networkFetcher:(YDNetworkFetcher*)fetcher didFailWithError:(NSError*)error{

if(_delegateFlags.didFailWithError) {

[_delegatenetworkFetcher:selfdidFailWithError:error];

}

}

- (void)networkFetcher:(YDNetworkFetcher*)fetcher didUpdateProgressTo:(float*)progress{

if(_delegateFlags.didUpdateProgressTo) {

[_delegatenetworkFetcher:selfdidUpdateProgressTo:progress];

}

}

@end

24.將類的實現(xiàn)代碼分散到便于管理的數(shù)個分類之中

使用分類機制把類的實現(xiàn)代碼劃分成易于管理的小塊碴里。

將應(yīng)該視為私有的方法歸入名叫Private的分類中沈矿,以隱藏實現(xiàn)細節(jié)。

@interfaceYDPerson :NSObject

@property(nonatomic,copy)NSString*firstName;

@property(nonatomic,copy)NSString*lastName;

@property(nonatomic,strong)NSArray*friends;

- (instancetype)initWithFirstName:(NSString*)firstName

LastName:(NSString*)lastName

Friends:(NSArray*)friends;

@end

@interfaceYDPerson (Friendship)

- (void)addFriend:(YDPerson*)person;

- (void)removeFriends:(YDPerson*)person;

- (BOOL)isFriendsWith:(YDPerson*)person;

@end

@interfaceYDPerson (Work)

- (void)performDaysWork;

- (void)takeVacationFromWork;

@end

@interfaceYDPerson (Play)

- (void)goToTheCinema;

- (void)goToSportsGame;

@end

25.總是為第三方類的分類名稱加前綴

向第三方類中添加分類時咬腋,總應(yīng)給其名稱加上你專用的前綴羹膳。

向第三方類中添加分類時,總應(yīng)給其中的方法名加上你專用的前綴根竿。

26.勿在分類中聲明屬性

把封裝數(shù)據(jù)所用的全部屬性都定義在主接口里陵像。

在class-continuation分類之外的其他分類中,可以定義存取方法寇壳,但盡量不要定義屬性醒颖。

27.使用class-continuation分類隱藏實現(xiàn)細節(jié)

通過class-continuation分類向類中新增實例變量。

如果某屬性在主接口中聲明為只讀壳炎,而類的內(nèi)部又要用設(shè)置方法修改此屬性泞歉,那么就在class-continuation分類中將其擴展為可讀寫。

把私有方法的原型聲明在class-continuation分類里面冕广。

若想使類遵循的協(xié)議不為人所知疏日,則可于class-continuation分類中聲明。

28.通過協(xié)議提供匿名對象

協(xié)議可在某種程度上提供匿名類型撒汉。具體的對象類型可以淡化成遵從某些一的id類型沟优,協(xié)議里規(guī)定了對象所應(yīng)實現(xiàn)的方法。

使用匿名對象來隱藏類型名稱或類名睬辐。

如果具體類型不重要挠阁,重要的是對象能夠響應(yīng)(定義在協(xié)議里的)特定方法,那么可使用匿名對象來表示溯饵。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侵俗,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子丰刊,更是在濱河造成了極大的恐慌隘谣,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啄巧,死亡現(xiàn)場離奇詭異寻歧,居然都是意外死亡,警方通過查閱死者的電腦和手機秩仆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門码泛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人澄耍,你說我怎么就攤上這事噪珊∩卧担” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵痢站,是天一觀的道長磷箕。 經(jīng)常有香客問我,道長瑟押,這世上最難降的妖魔是什么搀捷? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮多望,結(jié)果婚禮上嫩舟,老公的妹妹穿的比我還像新娘。我一直安慰自己怀偷,他們只是感情好家厌,可當(dāng)我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著椎工,像睡著了一般饭于。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上维蒙,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天掰吕,我揣著相機與錄音,去河邊找鬼颅痊。 笑死殖熟,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的斑响。 我是一名探鬼主播菱属,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼舰罚!你這毒婦竟也來了纽门?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤营罢,失蹤者是張志新(化名)和其女友劉穎赏陵,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饲漾,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡瘟滨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了能颁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡倒淫,死狀恐怖伙菊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤镜硕,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布运翼,位于F島的核電站,受9級特大地震影響兴枯,放射性物質(zhì)發(fā)生泄漏血淌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一财剖、第九天 我趴在偏房一處隱蔽的房頂上張望悠夯。 院中可真熱鬧,春花似錦躺坟、人聲如沸沦补。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夕膀。三九已至,卻和暖如春美侦,著一層夾襖步出監(jiān)牢的瞬間产舞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工菠剩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留易猫,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓赠叼,卻偏偏與公主長得像擦囊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嘴办,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容