《Swift进阶》 对一本书来说是一个很大胆的标题,所以我想我们应该先解释一下它意味着什么。
当我们开始本书第一版的写作时,Swift才刚刚一岁。我们推测这门语言会在进入第二个年头的时候继续高速地发展,不过尽管我们十分犹豫,但还是决定在Swift2.0测试版发布以前就开始写作。几乎没有别的语言能够在如此短的时间里就能吸引这么多的开发者前来使用。但是这留给了我们一个问题:如何写出“符合语言习惯”的Swift代码?对于某一个任务,有正确的做法吗?标准库给了我们一些提示,但是我们知道,即使是标准库本身也会随时间发生变化,它常常抛弃一切约定,又去遵守另一些约定。不过,在过去两年里,Swift高速进化着,而优秀的Swift代码标准也日益明确。
对于从其他语言迁移过来的开发者,Swift可能看起来很像你原来使用的语言,特别是它可能拥有你原来使用的语言中你最喜欢的那一部分。它可以像C语言一样进行低层级的位操作,但又可以避免许多未定义行为的陷阱。Ruby的教徒可以在像是map或filter的轻量级的尾随闭包中感受到宾至如归。Swift的泛型和C++的模板如出一辙,但是额外的类型约束能保证泛型方法在被定义时就是正确的,而不必等到使用的时候再进行判定。灵活的高阶函数和运算符重载让你能够以Haskell或者F#那样的风格进行编码。最后@objc关键字允许你像在Objective-C中那样使用selector和各种运行时的动态特性。
有了这些相似点,Swift可以去适应其他语言的风格。比如,Objective-C的项目可以自动地导入Swift中,很多Java或者C#的设计模式也可以直接照搬过来使用。在Swift发布的前几个月,一大波关于单子(monad)的教程和博客也纷至杳来。
但是失望也接踵而至。为什么我们不能像Java中的接口那样将协议扩展(protocol extension)和关联类型(associated type)结合起来使用?为什么数组不具有我们预想那样的协变(covariant)特性?为什么我们无法写出一个“函子”(functor)?有时候这些问题的答案是Swift还没有来得及实现这部分功能,但是更多时候,这是因为在Swift中有其他更适合这门语言的方式来完成这些任务,或者是因为Swift中这些你认为等价的特性其实和你原来的想象大有不同。
译者注:数组的协变特性指的是,包含有子类型对象的数组,可以直接赋值给包含有父类型对象的数组的变量。比如在Java和C#中,string是object的子类型,而对应的数组类型string[]可以直接赋值给声明为object[]类型的变量。但是在Swift中,Array<Parent>和Array<Child>之间并没有这样的关系。
和其他大多数编程语言一样,Swift也是一门复杂的语言。但是它将这些复杂的细节隐藏得很好。你可以使用Swift迅速上手开发应用,而不必知晓泛型、重载或者是静态调用和动态派发之间的区别等这些知识。你可能永远都不会需要去调用C语言的代码,或者实现自定义的集合类型。但是随着时间的推移,无论是想要提升你的代码的性能,还是想让程序更加优雅清晰,抑或是只是为了完成某项开发任务,你都有可能要逐渐接触到这些事情。
带你深入地学习这些特性就是这本书的写作目的。我们在书中尝试回答了很多“这个要怎么做”以及“为什么在Swift中会是这个结果”这样的问题,这种问题遍布各个论坛。我们希望你一旦阅读过本书,就能把握这些语言基础的知识,并且了解很多Swift的进阶特性,从而对Swift是如何工作的有一个更好的理解。本书中的知识点可以说是一个高级Swift程序员所必须了解和熟悉的内容。