namespaces in swift?

Objective-C 广泛被人诟病的一点就是没有 namespace 或者 module 的概念,而如果避免冲突的话只能靠给自己的类起个独特的名字来实现。

Objective-C classes must be named uniquely not only within the code that you’re writing in a project, but also across any frameworks or bundles you might be including.

当然啦,苹果也给出了自己的建议:

In order to keep class names unique, the convention is to use prefixes on all classes. You’ll have noticed that Cocoa and Cocoa Touch class names typically start either with NS or UI. Two-letter prefixes like these are reserved by Apple for use in framework classes.
Your own classes should use three letter prefixes. These might relate to a combination of your company name and your app name, or even a specific component within your app

也就说,你需要给自己的类名起一个独特的类名前缀,最好是三个或者四个大写字母,因为两个字母的是苹果自己保留的,你起得再好,也随时都可能被剥夺,如果和你的发生冲突的话,那么只能对不起啦,后果自负吧。

当 Swift 发布之后,很多人发现依然没有类似 namespace , package 这样的关键字来定义 namespace 或者 module,但是是不是 Swift 就和 Objective-C 一样,还是要必须通过起一个独特的名字来避免命名冲突呢?Swift 的发明者 Chris Lattner 在自己的 Twitter给出了答案:

Namespacing is implicit in swift, all classes (etc) are implicitly scoped by the module (Xcode target) they are in. no class prefixes needed

也就是说在 Swift 中,没有显示的声明,而且 namespace 不是按照文件来区分的,而是按照 XCode 中 Target 的 Product Module Name 名字来隐式的加以区别,其实这更像是 module 的概念。其实举一个很简单的例子,比如在我的 App 中,我有一个 class 的名字是 UIAlertView (当然这个例子很不恰当,但是却能说明问题), 而当我想使用 UIKit 中得 UIAlertView 的时候,我可以使用:

1
2
import UIkit
let alert = UIKit.UIAlertView(frame: frame)

而我要调用自己定义的 UIAlertView 的时候,可以直接使用:

1
let myAlert = UIAlertView()

这个时候并不冲突。其实这是一个很大的进步,而且会很有用处,比如我有两个库,一个叫 FrameworkA, 一个叫 FrameworkB, 它们之间唯一的区别就是 FrameworkB 是一个 mini 版的 FrameworkA,是在 FramworkA 的基础上做了一些删减,添加了少许的新功能。但是在我们项目中要根据服务器返回的数据不同使用不同的 Framework,而这个时候我们就可以通过调用 FrameworkA.test()FrameworkB.test() 来调用不同的方法。