# 15、用前缀避免命名空间冲突

因为OC没有命名空间这一机制，所以改用**为所有名称都加上适当的前缀**来变相实现命名空间（比如：你的公司叫`Effective Widgets`，那么可以使用`EWS`做前缀），减少重名几率。

​ 使用`Cocoa`创建应用程序时要注意了，`Apple`宣称其保留使用所有`两个字母前缀`的权利，所以你自己选用的前缀应该时三个字母的。（如果现在系统类里没有，保不准之后更新会出现跟你同名的`两个字母前缀`的系统类）

​ 不仅时类名，程序中所有名称都应加上前缀，如要为既有类新增`分类`，则**一定要给`分类`及`分类`中的方法加上前缀**。还有个可能会忽视的容易引发命名冲突的地方，就是类的实现文件中所用的`纯C函数`及`全局变量`，在编译好的目标文件中，这些名称都是“顶级符号”。如：

```objectivec
// 应加前缀：EOCSoundPlayerCompletion (项目前缀 + 类前缀 + 方法名)
void completion(SystemSoundID ssID, void *clientData) {
  // 触发代理，实现某些方法
}
- (void)playSound {
  // 播放声音
  AudioServiceAddSystemSoundCompletion(
    _systemSoundID,
      NULL,
      NULL,
      completion, // 播放完后回调
      (__bridge void *)self
  );
  AudioServicesPlaySystemSound(_systemSoundID);
}
```

​ 这段代码看上去很正常，不过再看看该类目标文件中的符号表（symbol table），就会发现问题了：

![播放音频回调符号表](https://1957578480-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQPrkdKRBulXdSdQ_wl%2F-MQPrtQBprnU7IBzECBa%2F-MQPsGA6AzkENcLVjOB6%2F%E6%92%AD%E6%94%BE%E9%9F%B3%E9%A2%91%E5%9B%9E%E8%B0%83%E7%AC%A6%E5%8F%B7%E8%A1%A8%402x.png?alt=media\&token=2dbed0b0-8327-47c7-a60a-0d27aaf7b6bb)

​ 虽说`completion`函数是在实现文件里定义的，并没有声明于头文件中，不过它仍是`顶级符号`。此时若在别处创建一个名为`completion`的函数，则会于链接时报错（`重复符号错误`）：

```objectivec
duplicate symbol _completion in:
    build/EOCSoundPlayer.o
  build/EOCAnotherClass.o
```

​ 如果将代码发布为程序库供他人使用，就更糟糕了。使用此程序库的开发者再无法创建名为`completion`的函数了。

​ 若自己编写程序库提供给他人使用，其中用到别人的三方库时，应该为其加上自己的前缀。因为别人可能也用到了这个库；亦或者：别人要用A版本，而你用的B版本，那么他必须自己再引入一份；更有甚：别人还用了另一个三方库（里也同样用了你用的三方库），此时如果都没加前缀，那么程序依然会出现重复符号错误。

![制作库时为使用到的三方库加前缀](https://1957578480-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQPrkdKRBulXdSdQ_wl%2F-MQPrtQBprnU7IBzECBa%2F-MQPsM5gSVNrIGMm6Yot%2F%E5%88%B6%E4%BD%9C%E5%BA%93%E6%97%B6%E4%B8%BA%E4%BD%BF%E7%94%A8%E5%88%B0%E7%9A%84%E4%B8%89%E6%96%B9%E5%BA%93%E5%8A%A0%E5%89%8D%E7%BC%80%402x.png?alt=media\&token=a8adf53e-dfa2-45f0-bc4f-19063cb87356)

要点：

* 选择与你的公司、应用程序或二者皆有关联之名称作为类名的前缀，并在所有代码中均使用这一前缀
* 若自己所开发的程序库中用到了第三方库，则应为其中的名称加上前缀
