Kotlin 编程核心基石—高阶函数

本文深入探讨了Kotlin中的高阶函数、Lambda表达式及其重要性。通过实例分析了函数类型、高阶函数和Lambda的关系,以及SAM转换。此外,还介绍了带接收者的函数类型,并展示了如何使用Kotlin DSL构建HTML的实战应用,强调了高阶函数在提升代码简洁性和效率上的作用。
摘要由CSDN通过智能技术生成

前言

1. 高阶函数有多重要?

高阶函数,在 Kotlin 里有着举足轻重的地位。它是 Kotlin 函数式编程的基石,它是各种框架的关键元素,比如:协程Jetpack ComposeGradle Kotlin DSL。高阶函数掌握好了,会让我们在读源码的时候“如虎添翼”。

本文将以尽可能简单的方式讲解 Kotlin 高阶函数Lambda 表达式,以及函数类型。在本文的最后,我们将自己动手编写一个 HTML Kotlin DSL

前期准备

  • 将 Android Studio 版本升级到最新
  • 将我们的 Demo 工程 clone 到本地,用 Android Studio 打开: github.com/chaxiu/Kotl…
  • 切换到分支:chapter_04_lambda
  • 建议各位小伙伴小伙伴跟着本文一起实战,实战才是本文的精髓

注:墙裂建议!时间比较充裕的小伙伴在文末观看案例实战的视频讲解

正文

1. 函数类型,高阶函数,Lambda,它们分别是什么?

1-1 函数类型(Function Type)是什么?

顾名思义:函数类型,就是函数的类型。

//         (Int,  Int) ->Float 
//           ↑      ↑      ↑
fun add(a: Int, b: Int): Float { return (a+b).toFloat() }

将函数的参数类型返回值类型抽象出来后,就得到了函数类型(Int, Int) -> Float 就代表了参数类型是 两个 Int 返回值类型为 Float 的函数类型。

1-2 高阶函数是什么?

高阶函数是将函数用作参数或返回值的函数。

上面的话有点绕,直接看例子吧。如果将 Android 里点击事件的监听用 Kotlin 来实现,它就是一个典型的高阶函数

//                      函数作为参数的高阶函数
//                              ↓
fun setOnClickListener(l: (View) -> Unit) { ... }
1-3 Lambda 是什么?

Lambda 可以理解为函数的简写

fun onClick(v: View): Unit { ... }
setOnClickListener(::onClick)

// 用 Lambda 表达式来替代函数引用
setOnClickListener({v: View -> ...})

看到这,如果你没有疑惑,那恭喜你,这说明你的悟性很高,或者说你基础很好;如果你感觉有点懵,那也很正常,请看后面详细的解释。


2. 为什么要引入 Lambda 和 高阶函数?

刚接触到高阶函数和 Lambda 的时候,我就一直有个疑问:为什么要引入 Lambda 和 高阶函数?这个问题,官方文档里没有解答,因此我只能自己去寻找。

2-1 Lambda 和 高阶函数解决了什么问题?

这个问题站在语言的设计者角度会更明了,让我们看个实际的例子,这是 Android 中的 View 定义,我省略了大部分代码:

// View.java
private OnClickListener mOnClickListener;
private OnContextClickListener mOnContextClickListener;

// 监听手指点击事件
public void setOnClickListener(OnClickListener l) {
    mOnClickListener = l;
}

// 为传递这个点击事件,专门定义了一个接口
public interface OnClickListener {
    void onClick(View v);
}

// 监听鼠标点击事件
public void setOnContextClickListener(OnContextClickListener l) {
    getListenerInfo().mOnContextClickListener = l;
}

// 为传递这个鼠标点击事件,专门定义了一个接口
public interface OnContextClickListener {
    boolean onContextClick(View v);
}

Android 中设置点击事件和鼠标点击事件,分别是这样写的:

// 设置手指点击事件
image.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        gotoPreview();
    }
});

// 设置鼠标点击事件
image.setOnContextClickListener(new View.OnContextClickListener() {
    @Override
    public void onContextClick(View v) {
        gotoPreview();
    }
});

请问各位小伙伴有没有觉得这样的代码很啰嗦?

现在我们假装自己是语言设计者,让我们先看看上面的代码存在哪些问题:

  • 定义方:每增加一个方法,就要新增一个接口:OnClickListenerOnContextClickListener
  • 调用方:需要写一堆的匿名内部类,啰嗦,繁琐,毫无重点

仔细看上面的代码,开发者关心的其实只有一行代码:

gotoPreview();

如果将其中的核心逻辑抽出来,这样子才是最简明的:

image.setOnClickListener { gotoPreview() }
image.setOnContextClickListener { gotoPreview() }

Kotlin 语言的设计者是怎么做的?是这样:

  • 用函数类型替代接口定义
  • 用 Lambda 表达式作为函数参数

与上面 View.java 的等价 Kotlin 代码如下:

//View.kt
var mOnClickListener: ((View) -> Unit)? = null
var mOnContextClickListener: ((View) -> Unit)? = null

fun setOnClickListener(l: (View) -> Unit) {
    mOnClickListener = l;
}

fun setOnContextClickListener(l: (View) -> Unit) {
    mOnContextClickListener = l;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值