第三章 接口与API设计—第20条:为私有方法名加前缀

一个类所做的事情通常都要比从外面看到的更多。编写类的实现代码时,经常要写一些只在内部使用的方法。笔者建议,应该为这种方法的名称加上某些前缀,这有助于调试,因为据此很容易就能把公共方法和私有方法区别开。
为私有方法名加前缀还有个原因,就是便于修改方法名或方法签名。对于公共方法来说,修改其名称或签名之前要三思,因为类的公共API不便随意改动。如果改了,那么使用这个类的所有开发者都必须更新其代码才行。而对于内部方法来说,若要修改其名称或签名,则只需同时修改本类内部的相关代码即可,不会影响到面向外界的那些API。用前缀把私有方法标出来,这样很容易就能看出哪些方法可以随意修改,哪些不应轻易改动。
具体使用何种前缀可根据个人喜好来定,其中最好包含下划线与字母p。笔者喜欢用p_作为前缀,p表示"private"(私有的),而下划线则可以把这个字母和真正的方法名区隔开。下划线后面的部分按照常用的驼峰法来命名即可,其首字母要小写。例如,包含私有方法的EOCObject类可以这样写:

#import <Foundation/Foundation.h>

@interface EOCObject : NSObject
- (void)publicMethod;
@end

@implementation EOCObject

- (void)publicMethod {
    …
}

- (void)p_privateMethod {
    …
}

@end

与公共方法不同,私有方法不出现在接口定义中。有时可能要在"class-continuation分类"(参见第27条)里声明私有方法,然而最近修订的编译器已经不要求在使用方法前必须先行声明了。所以说,私有方法一般只在实现的时候声明。
如果写过C++或Java代码,你可能就会问了: 为什么要这样做呢?直接把方法声明成私有的不就好了吗?Objective-C语言没办法将方法标为私有。每个对象都可以响应任意消息(参见第12条),而且可在运行期检视某个对象所能直接响应的消息(参见第14条)。根据给定的消息查出其对应的方法,这一工作要在运行期才能完成(参见第11条),所以Objective-C中没有那种约束方法调用的机制用以限定谁能调用此方法、能在哪个对象上调用此方法以及何时能调用此方法。开发者会在命名惯例中体现出"私有方法"等语义。新手也许不适应这一点,但是必须用心领悟Objective-C语言这种强大的动态特性。想掌握其动态特性,确实得花大功夫,不过培养良好的命名习惯也是一条成功之道。
苹果公司喜欢单用一个下划线作私有方法的前缀。你或许也想照着苹果公司的办法只拿一个下划线作前缀,这样做可能会惹来大麻烦: 如果从苹果公司提供的某个类中继承了一个子类,那么你在子类里可能会无意间覆写了父类的同名方法。鉴于此,苹果公司在文档中说,开发者不应该单用一个下划线作前缀。不能将方法限定于某个范围内,这也许是Objective-C的缺点,然而作为"动态方法派发系统"(dynamic method dispatch system,参见第11条)这个强大组件的一部分,此特性也带来了诸多好处。
你或许觉得刚才提到的那种情况不太常见,其实未必。例如,要在iOS应用程序中创建一个视图控制器,就得编写UIViewController的子类。自定义的视图控制器里可能保存着许多状态信息。你可能想编写一个方法,当视图出现在屏幕上时,可经由此方法把控制器里的所有状态都重置一遍。于是,该方法的实现代码也许会写成这样:

#import <UIKit/UIKit.h>

@interface EOCViewController : UIViewController
@end

@implementation EOCViewController
- (void)_resetViewController {
    // Reset state and views
}
@end

可问题是,UIViewController类本身其实已经实现了一个名叫_resetViewController的方法了!如果这样写的话,那么所有调用都将执行子类中的这个方法,本来该调用超类方法的地方现在调用的却是EOCViewController中覆写过的这个版本。由于超类中的同名方法并未对外公布,所以除非深入研究这个库,否则你根本不会察觉到自己在无意间覆写了这个方法。这毕竟是个用下划线开头的私有方法,所以没有对外公布也是合理的。由于超类方法永远不可能执行,所以这个视图控制器的行为很奇怪,到时你可能会纳闷: 为什么子类的这个方法调用得这么频繁呢,按道理不应该执行这么多次呀?
总之,在确定使用了前缀的情况下,如果子类所继承的那个类既不在苹果公司的框架中,也不在你自己的项目中,而是来自别的框架,那么除非该框架在文档中明示,否则你无法知道其私有方法所加的前缀是什么。此时可以把自己一贯使用的类名前缀(参见第15条)用作子类私有方法的前缀,这样能有效避免重名问题。同时还应该考虑到其他人会如何从你所写的类中继承子类,这也是私有方法应该加前缀的原因。除非使用一些相当复杂的工具,否则,在没有源代码的情况下,无法知道某个类在其公共接口之外还定义并实现了哪些方法。

要点

  • 给私有方法的名称加上前缀,这样可以很容易地将其同公共方法区分开。
  • 不要单用一个下划线做私有方法的前缀,因为这种做法是预留给苹果公司的。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容