美文网首页
Kotlin函数式编程 (3)✔️闭包与捕获变量

Kotlin函数式编程 (3)✔️闭包与捕获变量

作者: 狼性代码人 | 来源:发表于2019-06-06 08:33 被阅读0次
  • 闭包定义
  • Java 与 Koltin 中 Lambda 捕获局部变量区别
  • 闭包捕获的变量可以脱离原始作用域而存在

一、闭包定义

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

  闭包可以访问函数体之外的变量,这个过程称为捕获变量。

// 全局变量
var value = 0

fun main(args: Array<String>?) {
    // 局部变量
    var localValue = 20

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

    result(30)

    println("value = $value")
    println("localValue = $localValue")
}

2019-06-05 16:53:27.124 28646-28646/cn.ak.kot I/System.out: 52
2019-06-05 16:53:27.124 28646-28646/cn.ak.kot I/System.out: value = 1
2019-06-05 16:53:27.125 28646-28646/cn.ak.kot I/System.out: localValue = 21

  上述代码中 闭包是捕获 valuelocalValue 变量的 Lambda 表达式。

二、Java 与 Koltin 中 Lambda 捕获局部变量区别

  Java 中 Lambda 表达式捕获局部变量时,局部变量只能是 final 的。在 Lambda 体中只能读取局部变量,不能修改局部变量。而 kotlin 中没有这个限制,可以读取和修改局部变量。如下面代码:

// 声明了一个Java代码接口
@FunctionalInterface
public interface Clickable {
    void onClick();
}
// Java中的Lambda表达式局部变量捕获
public class Closure {

    private void closure(Clickable clickable) {
        clickable.onClick();
    }

    public void main(ArrayList<String> args) {
        int count = 0;
        closure(() -> {
            count += 1; // 1️⃣编译错误,count需要使用final修饰
        });
        System.out.println(count);
    }
}

  Java中代码第1️⃣行是编译不过的,必须设置为 countfinal 才能通过编译,但又不能对 count 进行修改,如果非要修改 count 只能把 count 声明为 Closure 的成员变量。

  对比 Kotlin 代码实现:

class Closure {

    private fun closure(clickable: Clickable) {
        clickable.onClick()
    }

    fun main(args: Array<String>) {
        var count: Int = 0
        closure(Clickable { count += 1 }) // 编译正常
        println(count)  // 2
    }
}

三、闭包捕获的变量可以脱离原始作用域而存在

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

fun sum(): (Int) -> Int { // 2️⃣
    var total = 0 // 3️⃣

    return { // 4️⃣
        total += it
        total
    }
}

fun main(args: Array<String>?) {
    val f1 = sum()  // 5️⃣
    println(f1(10))
    println(f1(10))
    println(f1(10))
    println(f1(10))
}

2019-06-05 17:20:55.912 30314-30314/cn.ak.kot I/System.out: 10
2019-06-05 17:20:55.912 30314-30314/cn.ak.kot I/System.out: 20
2019-06-05 17:20:55.912 30314-30314/cn.ak.kot I/System.out: 30
2019-06-05 17:20:55.913 30314-30314/cn.ak.kot I/System.out: 40

  代码第1️⃣行声明高阶函数sum()返回值类型为(Int) -> Int函数类型;第3️⃣行定义了一个total局部变量,作用域为sum()高阶函数内;第4️⃣行使用 Lambda 表达式作为 高阶函数sum()返回值。
  代码第5️⃣行声明变量 f1,注意 f1 类型是(Int) -> IntLambda表达式。连续执行 4次f1(10)后打印结果为10、20、30、40的累加结果,f1 又是Lambda表达式引用,而Lambda表达式的返回值是局部变量total,但是total的作用域是在高阶函数sum()中,每次 f1 执行完时,total变量的作用域就不存在了,可是 total 变量值都能够被保持,由此说明被捕获的变量都存储在一个特殊的容器内,而这个变量和函数一同存在。

相关文章

  • Kotlin函数式编程 (3)✔️闭包与捕获变量

    闭包定义Java 与 Koltin 中 Lambda 捕获局部变量区别闭包捕获的变量可以脱离原始作用域而存在 一、...

  • Kotlin 函数式编程思想 FP in Kotlin

    Kotlin 函数式编程思想 : FP in Kotlin 函数式编程特性 闭包和高阶函数 函数编程支持函数作为第...

  • Swift闭包

    闭包的定义闭包是一个捕获了上下文的常量或变量的匿名函数。 ?的全局函数是一种特殊的闭包,不捕获变量; ?的内嵌函数...

  • Rust编程语言-13-函数式编程(闭包和迭代器)

    Rust语言的设计吸收了许多其它语言的优秀设计,比如函数式编程和闭包 闭包closure 能捕获环境参数的匿名函数...

  • Swift-进阶 :闭包(一)使用&捕获原理

    本文主要分析闭包以及闭包捕获变量的原理 闭包 闭包是一个捕获了全局上下文的常量或者变量的函数,通俗来讲,闭包可以是...

  • python学习笔记十(函数式编程)

    函数式编程 闭包 由函数以及环境变量构成闭包,环境变量不受外部影响。 在函数内部定义另一个函数,内部函数使用包含其...

  • Swift 闭包底层探究

    闭包 闭包:一个函数和它所捕获的变量\常量环境组合起来,称为闭包(一般它捕获的是外层函数的局部变量\常量) 可以把...

  • swift基础_函数

    一.闭包简介 一个函数和它所捕获的变量/常量环境组合起来,成为闭包 如果闭包捕获了局部变量,那么会将该局部变量保存...

  • ReactiveCocoa入门笔记

    RAC是函数响应式编程思想的第三方框架 高阶函数:入参或者返回值是一个函数闭包:将外部的变量 进行捕获 RAC中的...

  • Swift中的闭包定义

    定义闭包变量 定义可选闭包变量 定义闭包别名 定义闭包常量 在函数内部 作为函数参数 作为函数参数(隐式参数类型)...

网友评论

      本文标题:Kotlin函数式编程 (3)✔️闭包与捕获变量

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