第2部分 故事的进阶要素 - 编程语言Swift的进阶部分
7 函数类型与闭包
7.1 概念通俗讲解
函数类型与闭包是Swift学习中的一个比较难的地方。
函数类型是变量的一种类型,指变量的各个类型中有一个类型是函数类型。
闭包是一组代码块,和函数有些相似。不过它俩具体的使用场景不太一样。
7.2 定义简洁介绍
对于函数类型与闭包,按照个人如下三个地方的总结来学习,理解起来会很容易些。
1.声明 2.赋值 3.使用 (使用函数类型变量时,一般叫做调用)
通过实际举例来说明,理解起来更容易些。
我们以定义一个整形类型的变量和函数类型的变量作对比来讲解声明,赋值,使用。
首先定义一个整形类型的变量
声明
赋值
使用
var temp = price
现在我们来定义一个函数类型的变量
声明
赋值
使用
实际编码时,当看到(Int,Int) -> Int这种形式时,记住这是函数类型的声明格式。
当看到price2(3,5)这种形式时,可能是调用函数,也可能是调用函数类型的变量。
下面着重来讲解下函数类型的赋值,即闭包。闭包的本质是一组代码块,和函数类似。
如下就是一个闭包
闭包首先需要一个{}包裹起来,中间用in关键字隔开,前面是参数,后面是逻辑代码。如果这个闭包有返回值,用return返回。上面这个闭包是需要返回整形数据的,所以用return关键字返回。
7.3 我的经验总结
因为很多编程语言是没有函数类型和闭包概念的,我在学习函数类型和闭包时一直在思考为什么要设计闭包,以及函数类型和闭包常用使用场景是什么。通过学习和实践,做了如下的总结
1). 函数类型和闭包常见的使用场景
(1) 闭包做为一个函数的参数,直接在这个函数的参数上实现功能
(2) 主线程中通过闭包,接收到服务端异步回调回来的通知后,再执行代码
(3) 通过闭包逆向传值
因为场景2和3涉及到了类,协议等还未讲解的知识,场景2和3会在后面具体讲解。这里通过UIButton(iOS系统的按钮控件)点击事件的例子,先讲解下第1个使用场景:闭包做为一个函数的参数,直接在这个函数的参数上实现功能。
注:UIButton后面会具体讲解,这里只需要知道UIButton是一个按钮即可。
下面的代码简单理解就是我添加了一个按钮,按这个按钮时触发一个逻辑。
var redButton = UIButton()
redButton.addTarget(self, action: #selector(tapRedButton), for: .touchUpInside)
func tapRedButton() {
print("运行逻辑")
}
用函数类型和闭包模拟
func addTarget(object: Int, action: (Int) -> Void, touch: Int){
action(100)
}
addTarget(object: 0, action: { (param: Int) in print("运行逻辑, 输出param的值 = \(param)")}, touch: 0)
注:第一个和第三个参数直接用Int类型来模拟,这里因为和闭包无关,可忽略。
通过这个模拟对比可看出。闭包一个用法就是如果一个函数的参数是另一个函数。如果使用闭包的写法。不用再去定义另一个函数,而直接实现功能,更简洁一些。
这里闭包和函数类型部分的代码,运行的结果是:
运行逻辑, 输出param的值 = 100
2). 函数类型的变量(或常量)和函数实现的对比
函数的功能是计算某个整数的平方
函数
func myFunc(param: Int) -> Int{
return param * param
}
函数类型的常量
let myClosures : (Int) -> Int = {(param: Int) in
return param * param
}
对函数进行调用 将返回9
函数类型的常量 将返回9
通过比较可以看出函数类型的常量和函数很多地方还是很相似的
3). 后置闭包
func person(age: Int, height: (Int,Int) -> Int ){
height(100,80)
}
正常调用person函数形式如下
person(age: 20, height: {(param1: Int, param2: Int) -> Int in
return param1 + param2}
)
当函数最后一个参数为闭包时,可以改为后置闭包的写法
person(age: 20) { (param1: Int, param2: Int) -> Int in
return param1 + param2
}
4). 闭包的简写
闭包的标准形式中{(price1: Int, price2: Int) in return price1 + price2}
没有返回值的话,return关键字是可以省略的。如果参数没有的话,in关键字也是可以省略的
所以闭包最简写形式可以只写闭包in后面的代码。
举例
func boy(age: () -> Void){
age()
}
无参数,无返回值,最简形式。调用boy函数
boy {
print("执行代码块")
}
5). 闭包的总结
回到刚开始说的函数类型和闭包的三个核心地方:声明,赋值,使用
声明
赋值
使用
这三个核心地方:"声明,赋值,使用"实际的用法
//声明:age: (Int) -> Void
func girl(age: (Int) -> Void){
//使用:age(20)
age(20)
}
//赋值
girl { (param) in
print(param)
}
闭包和函数类型的用法流程如下:通过函数类型的"使用"来发出一个通知,上面的代码部分就是代码age(20)。发出这个通知后,在函数类型"赋值"部分接收这个通知,根据接收的这个通知,执行后面的逻辑。
重点:我的理解闭包和函数类型使用的本质就是用来发通知,接收到通知后处理逻辑。如下这三个闭包常用的使用场景其实就是不同场景下的发送通知,接收到通知后处理逻辑
(1) 闭包做为一个函数的参数,直接在这个函数的参数上实现功能。
(2) 主线程中通过闭包,接收到获取服务端的异步回调的通知后再执行代码。
(3) 通过闭包逆向传值。
注:本人水平和能力有限,如果哪些地方写错了,请大家给我反馈,我会及时修改。