【2023】Kotlin教程 第二篇 面向对象与函数式编程 第13章 函数式编程基石——高阶函数和Lambda表达式 13.4 闭包与捕获变量

【2023】Kotlin教程

在这里插入图片描述

第二篇 面向对象与函数式编程

第13章 函数式编程基石——高阶函数和Lambda表达式

函数式编程思想虽然与面向对象一样立即悠久,但是支持函数式编程的计算机语言不过是近几年的事情。这些语言有Swift、Python、Java 8和C++ 11等,作为新生的语言Kotlin也支持函数式编程。

13.4 闭包与捕获变量

闭包(closure)是一种特殊的函数,它可以访问函数体之外的变量,这个变量和函数一同存在,即使已经离开了它的原始作用域也不例外。这种特殊函数一般是局部函数、匿名函数或Lambda表达式。

闭包可以访问函数体之外的变量,这个过程称为捕获变量。示例代码如下:

// 全局变量
var value = 10

fun main() {
    
    

    // 局部变量
    var localValue = 20

    var result = {
    
     a: Int ->
        value++
        localValue++
        val c = a + value + localValue
        println(c)
    }

    result(30) // 62
    println("localValue = " + localValue) // 21
    println("value = " + value) // 11
}

在这里插入图片描述

本例中的闭包是捕获value和localValue变量的Lambda表达式。在Lambda体中捕获变量value和localValue。

【给Java程序员的提示】Java中,Lambda表达式捕获局部变量时,局部变量只能是final的。在Lambda体中只能读取局部变量,不能修改局部变量。而Kotlin中没有这个限制,可以读取和修改局部变量

【注意】闭包捕获变量后,这些变量被保存在一个特殊的容器中被存储起来。即便是声明这些变量的原始作用域已经不存在,闭包体中仍然可以访问这些变量。

下面是一个局部函数示例:

fun makeArray(): (Int) -> Int {
    
    
    var ary = 0

    // 局部函数捕获变量
    fun add(element: Int): Int {
    
    
        ary += element
        return ary
    }

    return ::add
}

fun main() {
    
    

    val f1 = makeArray()
    println("---f1---")

    println(f1(10))
    println(f1(20))
    println(f1(30))
}

在这里插入图片描述

ary 变量的作用域是makeArray 函数体,在局部函数add 函数体内,修改了变量ary 的值,并返回。

这样一来,当主函数中进行调用时,f1 是局部函数add 的一个变量,而且需要注意的是,f1 每次调用的时候,ary 的变量作用域已经不存在了,所以ary 变量可以被保持。

这个栗子也可以用匿名函数实现,代码如下:

fun makeArray(): (Int) -> Int {
    
    
    var ary = 0

    // 局部函数捕获变量
    return fun(element: Int): Int {
    
    
        ary += element
        return ary
    }
}

fun main() {
    
    

    val f1 = makeArray()
    println("---f1---")

    println(f1(10))
    println(f1(20))
    println(f1(30))
}

在这里插入图片描述

makeArray函数返回一个Lambda表达式,。比较Lambda表达式与匿名函数和局部函数,会发现Lambda表达式代码最为简洁,最后实现的结果完全一样。

猜你喜欢

转载自blog.csdn.net/weixin_44226181/article/details/130024492
今日推荐