美文网首页
Swift5.1学习随笔之闭包Closure

Swift5.1学习随笔之闭包Closure

作者: SAW_ | 来源:发表于2020-04-16 17:05 被阅读0次

闭包闭包表达式不是一个东西

闭包定义:
1、一个函数和它所捕获的变量、常量环境组合起来,称之为闭包

  • 一般指定义在函数内部的函数
  • 一般它捕获的是外层函数的局部变量、常量
func fn() -> () -> () {
    var a = 10
    func fn1() {
        a = 11
    }
    return fn1
}

例子🌰

typealias Fn = (Int) -> Int
func getFn() -> Fn {
    var num = 0
    func plus(_ i: Int) -> Int {
        num += 1
        return num
    }
    return plus
} // 返回的plus和num形成了闭包

var fn = getFn()
print(fn(1)) //1
print(fn(2)) //3
print(fn(3)) //6
print(fn(4)) //10

num是函数局部变量,正常来说调用getFn之后分配一段连续的栈空间,空间内部有8个字节用来存储num变量0
一旦return返回之后意味着函数调用结束,栈空间会被回收,num变量会被销毁,既然栈空间被回收,为何能调用fn

全局变量fn内部持有函数plus的地址信息。
plus持有了局部变量num,根据汇编代码来看,getFn函数内部调用了swift_allocObject,申请了一块堆空间给变量num,使得不会因为函数调用之后被销毁。

可以将闭包想象成一个类的实例对象

  • 内存在堆空间
  • 捕获的局部变量、常量就是对象的成员(存储属性)
  • 组成闭包的函数就是类内部定义的方法
class Closure {
    var num = 0
    func plus(_ i: Int) -> Int {
        num += i
        return num
    }
}
var cs1 = Closure()
print(cs1.plus(1)) //1
print(cs1.plus(2)) //3
print(cs1.plus(3)) //6

如果返回值是函数类型,那么参数的修饰要保持统一

func add(_ num: Int) -> (inout Int) -> Void {
    func plus(v: inout Int) {
        v += num
    }
    return plus
}
var num = 5
add(20)(&num)
print(num)

自动闭包

看个例子🌰

//如果第1个数大于0,返回第1个数,否则返回第2个数
func getFirstPositive(_ v1: Int, _ v2: Int) -> Int {
    return v1 > 0 ? v1 : v2
}
getFirstPositive(10, 20) // 10
getFirstPositive(-2, 20) // 20
getFirstPositive(0, -4) // -4
func getNumber() -> Int {
    let a = 10
    let b = 11
    print("test-----")
    return a + b
}
//返回第1个参数,同时调用了第2个参数的函数实现,输出print("test-----")
getFirstPositive(10, getNumber()) //10

上面函数调用中,第1个参数10大于0,所以返回10,那么第2个参数getNumber()的调用就没必要,浪费资源,如何优化?

//将v2变成一个函数
func getFirstPositive(_ v1: Int, _ v2: () -> Int) -> Int {
    return v1 > 0 ? v1 : v2()
}

getFirstPositive(-10) {
    let a = 10
    let b = 11
    print("test-----111")
    return a + b
} //第1个参数小于0,返回第2个参数,调用了print("test-----111")

getFirstPositive(10) {
    let a = 10
    let b = 11
    print("test-----222")
    return a + b
} //第1个参数大于0,返回第1个参数,没有输出print("test-----111"),说明第2参数没调用

上面的例子🌰中,如果代码比较精简的话,可读性不高:

getFirstPositive1(10, {20})
getFirstPositive1(10) {20}

Swift提供了一个语法:自动闭包
添加关键词:@autoclosure

func getFirstPositive(_ v1: Int, _ v2: @autoclosure () -> Int) -> Int {
    return v1 > 0 ? v1 : v2()
}
getFirstPositive(10, 20)

注意点
1、@autoclosure会自动将20封装成闭包{ 20 }
2、@autoclosure只支持 () -> T 格式的参数
3、@autoclosure并非只支持最后1个参数

func getFirstPositive3(_ v1: Int, _ v2: @autoclosure () -> Int,  _ v3: Int,  _ v4: Int) -> Int {
    return v1 > 0 ? v1 : v2()
}
getFirstPositive3(10, 20, 30, 40)

4、空合并运算符??使用了@autoclosure技术
5、有@autoclosure、无@autoclosure构成了函数重载

func getFirstPositive(_ v1: Int, _ v2: () -> Int) -> Int {
    return v1 > 0 ? v1 : v2()
}

func getFirstPositive(_ v1: Int, _ v2: @autoclosure () -> Int) -> Int {
    return v1 > 0 ? v1 : v2()
}

getFirstPositive(10, 20) //调用 @autoclosure 的getFirstPositive
getFirstPositive(10, {30}) //调动无 @autoclosure 的getFirstPositive

6、为了避免与期望冲突,使用了@autoclosure的地方最好明确注释清楚:这个值会被推迟执行

相关文章

  • Swift5.1学习随笔之闭包Closure

    闭包跟闭包表达式不是一个东西 闭包定义:1、一个函数和它所捕获的变量、常量环境组合起来,称之为闭包 一般指定义在函...

  • 闭包

    学习Javascript闭包(Closure)

  • JavaScript----闭包

    javascript之闭包 闭包的概念     闭包(closure)是 JavaScript 的一种语法特性。 ...

  • 关于rust中的闭包(一)

    闭包 在计算机中,闭包 Closure, 又称词法闭包 Lexical Closure 或函数闭包 functio...

  • 关于闭包

    闭包的英文是closure,又称词法闭包(Lexical Closure)和函数闭包(Function Closu...

  • 理解闭包

    闭包 何为闭包 闭包(Closure)是词法闭包(Lexical Closure)的缩写 高级程序设计中写有权访问...

  • python之闭包与装饰器

    1 闭包 维基百科给出的解析:闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭...

  • 闭包,定时器

    问题 1.什么是闭包? 有什么作用 闭包(英语:Closure),又称词法闭包(Lexical Closure)或...

  • Swift5.1学习随笔之闭包表达式Closure Expres

    在swift中,可以通过func定义一个函数,也可以通过闭包表达式定义一个函数 通过func定义一个函数 通过闭包...

  • [Code] 优雅地使用python闭包

    在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(funct...

网友评论

      本文标题:Swift5.1学习随笔之闭包Closure

      本文链接:https://www.haomeiwen.com/subject/xpcdvhtx.html