5.3 理解闭包结构

闭包结构对于编程初学者来说可能会难于理解一些。在学习关于闭包的过程中,读者首先应该理解闭包的结构与实质。

5.3.1 闭包的语法结构

使用Xcode开发工具创建一个命名为Closures的playground文件,本章将在其中进行代码的演练。5.2节中向读者介绍了有关函数的内容,函数的设计思路是将有一定功能的代码块包装在一起,通过函数名实现复用。闭包和函数有着类似的作用,然而闭包的设计大多数情况下并不是为了代码的复用,而是传递功能代码块和处理回调结构。首先,一个完整的函数包含函数名、参数列表、返回值和函数体,示例如下:

将上面函数的功能使用闭包来实现,代码如下:

上面的代码创建了一个名为myClosures的闭包常量,闭包在语法上有这样的标准结构:{(参数列表)->返回值in闭包体}。首先闭包的最外层由大括号包围,内部由闭包关键字in来进行分割,关键字in前面为闭包结构的参数列表和返回值,其书写规则与函数一致,in关键字后面为闭包体,用于实现具体功能。上面示例的闭包和函数原理上完全相同,并且闭包也可以像函数一样被调用,示例代码如下:

    //对函数进行调用 将返回9
    myFunc(param: 3)
    //对闭包进行调用 将返回9
    myClosures(3)

与函数不同的是,闭包的返回值是可以省略的,在闭包体中,如果有return返回,则闭包会自动将return的数据类型作为返回值类型,上面的闭包代码也可以简写为如下样式:

5.3.2 通过实现一个排序函数来深入理解闭包

在实践中分析与解决问题是学习编程的一条捷径。本节将带领读者通过分析问题、探讨解决方案、进行初步实现、优化实现方式等一步步深入了解闭包的用法。学习这种分析解决问题的方式在编程中十分有益,其思路如图5-1所示。

图5-1 分析与解决问题思路

在实际开发中,开发者经常会遇到不同的排序需求,例如对商品价格排序、文章热度排序、消息时间先后排序、学生成绩排序等。很多情况下,开发者要排序的对象并不是简单的数字类型值或者字符串类型值,而是自定义的复杂对象,也就是开发者常用的类。对于这种类型的排序需求,应该如何实现呢?首先应该明确需求问题:

(1)应该实现一个函数,来对数组类型排序。

(2)数组中的元素可以是任意的复杂类型。

实现根据复杂类型数据中的某一个属性进行排序,例如学生的成绩。

(1)针对上面提出的需求问题,设计初步的实现思路。

(2)以通用的数组类型作为函数的参数。

若要实现对自定义复杂类型的排序操作,需要将排序算法作为参数传入函数。

编写函数的结构示例如下:

提示

Any在Swift语言中代表任意类型。

mySort()函数中需要传入两个参数,一个是要进行排序的数组数据,另一个是一个闭包排序方法,这个闭包有两个Int类型的参数,表示数组中两个相邻的元素。第1个参数表示前一个元素,第2个参数表示后一个元素,这个闭包有一个Bool类型的返回值,返回true则表示正向排序,即参数中的第1个元素和第2个元素不交换位置,返回false表示逆向排序,即参数中的第1个元素和第2个元素交换位置。之后,根据上面的分析来对mySort函数进行实现,代码如下:

如上代码所示,使用了冒泡排序算法来进行排序操作,而具体两个元素的排序规则是由闭包sortClosure来实现的。swap()函数是Swift语言中的一个交换函数,用来实现数组元素的交换,由于需要对原数组数据进行操作,需要使用inout类型的数组参数。

先使用整型数组来对编写的排序函数进行测试,代码如下:

提示

as!的作用是类型转换。

编写一个自定义的类来进行排序测试,示例如下:

以上代码模拟了一个学生类,每一个学生对象由名字和分数组成,闭包实现了对学生分数的排序规则。