每天了解一点不一样的 Swift 小知识
代码截图
小笔记
这段代码想传达什么意思
试想一下,假设你定义了一个 Command 类型,针对命令执行错误的状况,我们八成会用一个继承自 Error 类型的子类来描述错误类型,那么问题来了,这个类型的名字叫什么?
看起来 Error 是最简单优雅的,所以你的代码可能会写成如下的样式
1 | extension Command { |
只是很可惜,这么写代码会报错,一种解决方案就是我们把代码改成
1 | extension Command { |
这种方案虽然解决了问题,但不够优雅,主要是在类型的命名上,当我们要引用 Command 里面的这个内嵌类型时,我们会怎么写代码呢,必定是 Command.CommandError.missing
,看到这似乎嗅到了一点点 Objective-C 那又臭又长的命名味道,那么有更好的解决方案么?
有,也就是我们说的第二种方案,用 Swift.
来解决与命名冲突的问题,此时代码就需要这么写了
1 | extension Command { |
第二种方案是怎么解决问题的
在正式解释前,我们需要知道今天的话题本质是命名冲突引起的,当然,这里还需要明确一点的就是,命名冲突有 2 种情况,一种是类型之间的冲突,一种是 module 级别的冲突,
对于类型之间的冲突,是说同一个 Framework 下,如何区分同名类型,这个使用 Swift 里面的嵌套类型就可以解决,下面是一个示例
1 | // A.framework |
而对于 Module 级别的冲突,是说如何区分 A Framework 和 B Framework 里面的同名类型,这个问题在 Swift 里也有解决的办法,通过指明类型所在的 Framework 即可。
1 | // A.framework |
上面的内容或多或少都与 Swift 命名空间的知识相关联,而关于 Swift 命名空间的官方文档,我并没有找到太多,只找到 2 份比较有分量的材料,感兴趣的同学可以看看:
Swift 之父 Chris 在 Twitter 上的一些说明:传送门
Matt 大神在 SO 上的回答:传送门
结合今天的内容来总结一下上面 2 位大牛表达的观点就是说:
针对 module 级别的命名冲突,Swift 会优先考虑你代码中的命名,如果你想要使用其他库的命名,需要显示的指明,例如用 Swift.Error
或者 Foundation.NSArray
来指明这个类型不是当前代码中的类型。
好了,今天的内容就差不多了。
one more thing,还是关于命名空间的一些“技巧”,我们也可以在 Apple 公司新推出的 Combine 框架里看到,例如用 enum 做 namespace:传送门