第20条:为私有方法名加前缀
本條要點(diǎn):(作者總結(jié))
- ?給私有方法的名稱加上前綴,這樣可以很容易地將其同公共方法區(qū)分開。
- 不要單用一個(gè)下劃線做私有方法的前綴,因?yàn)檫@樣做法是預(yù)留給蘋果公司用的。
?
一個(gè)類所做的事情通常都要比從外面看到的更多。編寫類的實(shí)現(xiàn)代碼時(shí),經(jīng)常要寫一些只在內(nèi)部使用的方法。筆者建議,應(yīng)該為這種方法的名稱加上某些前綴,這有助于調(diào)試,因?yàn)閾?jù)此很容易就能把公共方法和私有方法區(qū)別開。
為私有方法名加前綴還有個(gè)原因,就是便于修改方法名或方法簽名。對(duì)于公共方法來說,修改其名稱或簽名之前要三思,因?yàn)轭惖墓?API 不便隨意改動(dòng)。如果改了,那么使用這個(gè)類的所有開發(fā)者都必須更新其代碼才行。而對(duì)于內(nèi)部方法來說,若要修改其名稱或簽名,則只需要同時(shí)修改本類內(nèi)部的相關(guān)代碼即可,不會(huì)影響到面向外界的那些 API。用前綴把私有方法標(biāo)出來,這樣很容易就能看出哪些方法可以隨意修改,哪些不應(yīng)輕易改動(dòng)。
具體使用何種前綴可根據(jù)個(gè)人喜好來定,其中最好包含下劃線與字母p。筆者喜歡用 p_ 作為前綴,p 表示 “private”(私有的),而下劃線則可以把這個(gè)字母和真正的方法名區(qū)隔開。下劃線后面的部分按照常用的駝峰法來命名即可,其首字母要小寫。例如,包含私有方法的 EOCObject 類可以這樣寫:
1 #import <Foundation/Foundation.h> 2 3 @interface EOCObject : NSObject 4 5 - (void)publicMethod; 6 7 @end 8 9 #import "EOCObject.h" 10 11 @implementation EOCObject 12 13 - (void)publicMethod { 14 /* ... */ 15 } 16 17 - (void)p_privateMethod { 18 /* ... */ 19 } 20 21 @end與公共方法不同,私有方法不出現(xiàn)在接口定義中。有時(shí)可能要在 “class-continuation 分類”里聲明私有方法,然而最近修訂的編譯器已經(jīng)不要求在使用方法前必須先行聲明了。所以說,私有方法一般只在實(shí)現(xiàn)的時(shí)候聲明。
如果寫過 C++ 或 Java 代碼,你可能就會(huì)問了:為什么要這樣做呢?直接把方法聲明成私有的不就好了嗎?Objective-C 語言沒有辦法將方法標(biāo)為私有。每個(gè)對(duì)象都可以響應(yīng)任意消息,而且可在運(yùn)行期檢視某個(gè)對(duì)象所能直接響應(yīng)的消息。根據(jù)給定的消息查出其對(duì)應(yīng)的方法,這一工作要在運(yùn)行期才能完成,所以 Objective-C 中沒有那種約束方法調(diào)用的機(jī)制用以限定誰能調(diào)用此方法、能在哪個(gè)對(duì)象上調(diào)用此方法以及何時(shí)能調(diào)用此方法。開發(fā)者會(huì)在命名慣例中體現(xiàn)出 “私有方法”等語義。新手也許不適應(yīng)這一點(diǎn),但是必須用心領(lǐng)悟 Objective-C 語言這種強(qiáng)大的動(dòng)態(tài)特性。想掌握其動(dòng)態(tài)特性,確實(shí)得花大功夫,不過培養(yǎng)良好的命名習(xí)慣也是一條成功之道。
蘋果公司喜歡單用一個(gè)下劃線作為私有方法的前綴。你或許也想照著蘋果公司的辦法只拿一個(gè)下劃線作前綴,這樣做可能會(huì)惹來大麻煩:如果從蘋果公司提供的某個(gè)類中繼承了一個(gè)子類,那么你在子類里可能會(huì)無意間覆寫了父類的同名方法。鑒于此,蘋果公司在文檔中說,開發(fā)者不應(yīng)該單用一個(gè)下劃線做前綴。不能將方法限定于某個(gè)范圍內(nèi),這也許是 Objective-C 的缺點(diǎn),然而作為 “動(dòng)態(tài)方法派發(fā)系統(tǒng)”(dynamic method dispatch system)這個(gè)強(qiáng)大組件的一部分,此特性也帶來了諸多好處。
你或許覺得剛才提到的那種情況不太常見,其實(shí)未必。例如,要在 iOS 應(yīng)用程序中創(chuàng)建一個(gè)視圖控制器,就得編寫 UIViewController 的子類。自定義的視圖控制器里可能保存著許多狀態(tài)消息。你可能想編寫一個(gè)方法,當(dāng)視圖出現(xiàn)在屏幕上時(shí),可經(jīng)由此方法把控制器里的所有狀態(tài)都重置一遍。于是,該方法的實(shí)現(xiàn)代碼也許會(huì)寫成這樣:
1 #import <UIKit/UIKit.h> 2 3 @interface EOCViewController : UIViewController 4 5 @end 6 7 8 #import "EOCViewController.h" 9 10 @interface EOCViewController () 11 12 @end 13 14 @implementation EOCViewController 15 16 - (void)_resetViewController { 17 // Reset state and views 18 19 } 20 21 - (void)viewDidLoad { 22 [super viewDidLoad]; 23 // Do any additional setup after loading the view. 24 } 25 26 - (void)didReceiveMemoryWarning { 27 [super didReceiveMemoryWarning]; 28 // Dispose of any resources that can be recreated. 29 } 30 31 /* 32 #pragma mark - Navigation 33 34 // In a storyboard-based application, you will often want to do a little preparation before navigation 35 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 36 // Get the new view controller using [segue destinationViewController]. 37 // Pass the selected object to the new view controller. 38 } 39 */ 40 41 @end可問題是,UIViewController 類本身其實(shí)已經(jīng)實(shí)現(xiàn)了一個(gè)名叫 _resetViewController 的方法了!如果這樣寫的話,那么所有調(diào)用都將執(zhí)行子類中的這個(gè)方法,本來該調(diào)用超類方法的地方現(xiàn)在調(diào)用的卻是 EOCViewController 中覆寫過的這個(gè)版本。由于超類中的同名方法并未對(duì)外公布,所以除非深入研究這個(gè)庫,否則你根本不會(huì)察覺到自己在無意間覆寫了這個(gè)方法。這畢竟是個(gè)用下劃線開頭的私有方法,所以沒有對(duì)外公布也是合理的。由于超類方法永遠(yuǎn)不可能執(zhí)行,所以這個(gè)視圖控制器的行為會(huì)很奇怪,到時(shí)你可能會(huì)納悶:為什么子類的這個(gè)方法調(diào)用得這個(gè)頻繁呢,按道理不應(yīng)該執(zhí)行這么多次呀?
總之,在確定使用了前綴的情況下,如果子類所繼承的那個(gè)類既不在蘋果公司的框架中,也不在你自己的項(xiàng)目中,而是來自別的框架,那么除非該框架在文檔中明示,否則你無法知道其私有方法所加的前綴是什么。此時(shí)可以把自己一貫使用的類名前綴用作子類私有方法的前綴,這樣能有效避免重名問題。同時(shí)還應(yīng)該考慮到其他人會(huì)如何從你所寫的類中繼承子類,這也是私有方法應(yīng)該加前綴的原因。除非使用一些相當(dāng)復(fù)雜的工具,否則,在沒有源代碼的情況下,無法知道某個(gè)類在其公共接口之外還 定義并實(shí)現(xiàn)了哪些方法。
END
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/chmhml/p/7153396.html
總結(jié)
以上是生活随笔為你收集整理的第20条:为私有方法名加前缀的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js 添加事件 attachEvent
- 下一篇: Git基础命令(一)