Serie de reaprendizaje de Kotlin: funciones de orden superior

¡Acostúmbrate a escribir juntos! Este es el primer día de mi participación en el "Nuggets Daily New Plan·Desafío de actualización de abril", haz clic para ver los detalles del evento

prefacio

Este es el primer artículo de la serie de reaprendizaje de kotlin. Con respecto a las funciones de orden superior, aprenderá después de leer este artículo con paciencia:

  • Comprender la esencia de las funciones de orden superior de Kotlin
  • Comprender las expresiones lambda en kotlin
  • Comprender la diferencia entre lambda de kotlin y java lambda

¿Por qué usar funciones de orden superior como el primer artículo de la serie de reaprendizaje de kotlin? ¡Sí, porque importa! ! ! Si no domina las funciones de orden superior, muchas sintaxis de kotlin le parecerán incómodas o incluso completamente incomprensibles, como las extensiones de kotlin, las corrutinas, DSL, etc., que casi todas están estrechamente relacionadas con las funciones de orden superior, por lo que puede ser dijo que no lo harán Las funciones de orden superior no son diferentes de escribir Java

tipo de función

¿Hay tipos de funciones en Java? No, los tipos de datos de Java solo incluyen tipos de datos básicos como int, long y tipos de referencia como String y array.

Entonces, ¿por qué Kotlin introduce otro tipo de función? cual es el efecto

Supongamos que existe tal lógica ahora: nosotros mismos definimos una función, pero hay una parte de la lógica en esta función que la persona que llama quiere definir, es decir, la persona que llama pasa un fragmento de lógica de código. ¿Hay alguna manera de implementar esto en Java?

Sí, al usar la interfaz, como el método de escucha de eventos de clic SetOnClickListener, recibe una interfaz. Implementamos OnClickListenerla interfaz de forma anónima para pasar una parte de la lógica del código al pasado.

Debido a que Java no admite tipos de funciones, solo podemos envolver esta función con una interfaz, por lo que esta es una forma de salvar al país de una curva. Por lo general, puede que no importe si hay una función de finalización automática de IDE, pero para lograr esto, somos muy La lógica común es definir una interfaz cada vez y luego implementarla Es un poco doloroso ver tantos códigos redundantes.

Por lo tanto, el tipo de función se introduce en kotlin para resolver este tipo de problema, de modo que la función también se puede usar directamente como parámetro o valor de retorno de otra función.

Representación de tipos de funciones

Debido a que entre diferentes funciones, la principal diferencia es la diferencia en los parámetros de entrada y los valores devueltos, por lo que la fórmula de expresión del tipo de función es la siguiente:

(parámetro) -> valor de retorno

Los corchetes en el lado izquierdo de la flecha indican el tipo de información de los parámetros de entrada (hay varios parámetros separados por ","), y el lado derecho de la flecha es la información del tipo de valor de retorno, consulte las castañas

// 表示的函数有两个Int类型的参数,返回值也是Int
(IntInt)->Int

// 函数没有入参,返回值是空的
()->Unit
复制代码

Funciones de orden superior

定义:如果一个函数的参数或者返回值是函数类型,那么这个函数就称之为高阶函数

例如

// 定义一个函数funA,接收一个函数类型的参数
fun funA(funParam: (Int) -> Int) {
    funParam(1)
}

// 定义一个函数funB,该函数入参为一个Int,返回值为一个Int
fun funB(param: Int): Int {
    return param+1
}

// 调用
funA(::funB)

复制代码

如上代码,函数funA就是一个高阶函数,因为他的入参包含了一个函数类型

又定义了一个函数funB,入参和返回值正好满足funA接收的函数类型,所以就可以把funB这个函数传递给funA

注意我们在调用的时候,不是直接把funB这个名字标识符传给funA,而是在前面加了一个::,那这个“::”是干什么的呢?

这个双冒号的写法叫做函数引用,也就是说::funB这个是指向函数funB的,为什么又需要整这些花里胡哨的,因为函数他毕竟本质还是一个函数,函数之所以可以作为参数传递给另外一个函数,他的本质是kotlin可以把函数包装为一个对象,也就是说::funB是一个函数类型的对象

不过实际开发中我目前很少用这种方式,大多数都是用匿名函数和lambda,这个才是重点,下面马上会讲到

匿名函数

没有名字的函数就叫匿名函数,还是上面那个demo,我们完全可以不单独定义一个函数funB,而是直接用匿名函数


funA(fun(param:Int):Int{
    return param+1
})

// 或者可以直接把匿名函数赋值给一个变量
val d = fun(param: Int): Int {
    return param+1
}
funA(d)
复制代码

我们看到这里匿名函数可以直接传递给函数,也可以直接赋值给变量,所以它跟上面的::funB就是等价的,也就是说匿名函数实质上是一个函数类型的对象

lambda

上面使用匿名函数的方式看着还是有点别扭,总感觉很臃肿,而kotlin的宗旨就是简洁,所以就有了lambda,像下面这样

funA({param:Int ->
    param+1
})
复制代码

lambda在匿名函数的基础上又省略了一些代码,包括省略了fun关键字,把参数也直接放在了大括号里面,这样看起来简洁了不少,不过lambda的简洁还不远不如此,下面会一步步简化

先看看lambda的标准格式

{参数->函数体}

lambda的内容都在一个大括号里面,用箭头分割成两部分,箭头左边是参数,箭头右边是函数体,如果没有参数,箭头以及左边的就直接省略不写

// 没有参数直接省略箭头和左边的内容
val lambda1 = { println("无参数的lambda") }


val lambda2 = { param: Int ->
    println("带参数的lambda$param")
}

// lambda的函数体的最后一行的结果表示的就是返回值
val lambda3 = { param: Int ->
    println("带参数的lambda$param")
    param
}
复制代码

上面的栗子展示了有参数和没有参数的lambda情况,另外值得注意的是lambda的最后一行的执行结果就是这个函数的返回值,例如上述lambda2的最后一行为println("带参数的lambda$param"),所以他的返回值类型为Unit,lambda3的最后一行是param,所以他的返回值就是这个param,也就是Int类型的

下面继续看看lambda表达式还能怎么简写

1.如果lambda是函数的最后一个参数,那么就可以把lambda写在括号外面

funA(){ param: Int ->
    param + 1
}
复制代码

2.如果函数只有lambda一个参数,括号里面就是空的,写了有何用,省略

funA{ param: Int ->
    param + 1
}
复制代码

3.kotlin支持类型推导,所以lambda中的参数类型也能省略

funA(){ param ->
    param + 1
}
复制代码

4.如果lambda只有一个参数,也可以省略

funA {
    it + 1
}
复制代码

如果lambda只有一个参数的时候,会默认提供一个名为it的参数来表示这个入参,在lambda内可以直接使用,不用声明

为什么越来越任性,啥都可以省略,那是因为kotlin坚持只要能推断出来的地方,能不写的代码就不写,例如这个地方的参数为什么可以省略,就是因为他能推导出来,从哪儿推导呢?肯定是函数定义的地方,函数funA在定义的时候就声明了这个函数的类型,包括参数类型,返回类型

那如果lambda有多个参数了?

fun funAA(funParam:(Int,Int)->Int){
    funParam(1,1)
}

// 必须写上参数,如果参数没有被使用,可以使用_代替
funAA { _, i2 -> i2+1 }
复制代码

多个参数就需要指明参数的名字了,如果参数没有使用,就可以使用_代替

kotlin的lambda和java的lambda的对比

java的lambda是在java8引入的,是针对单抽象SAM(Single Abstract Method)接口的简化使用,例如Runnable

// 原始写法
new Thread(new Runnable(){

    @Override
    public void run() {
        
    }
});

// 引入lambda之后
new Thread(() -> {
    int i = 1;
});

复制代码

而kotlin的lambda是一个函数对象,划重点它是一个对象,是一个函数类型的对象,所以它可以作为参数直接赋值给别的变量,而java中的lambda是做不到的,他只能用在单抽象接口的地方,只是一种写法上的变化,本质并没有改变,还是匿名内部类

En kotlin, para esta interfaz SAM, también se realiza una conversión compatible, que convierte directamente la función que usa la interfaz SAM en una función de orden superior, por lo que la lambda de kotlin también se puede aplicar directamente.

Thread { val i = 1 }
复制代码

Lo anterior es todo el contenido de las funciones de orden superior de kotlin, de hecho no es dificil, pero puede ser un poco desacostumbrado a aprender al principio, pero aun así es necesario decir que las funciones de orden superior de kotlin son muy importantes , sobre todo lambda, siempre y cuando se suele escribir más, es muy sencillo

Consulte el artículo del tipo grande:

Funciones de orden superior de Kotlin

Expresiones lambda en Kotlin

Supongo que te gusta

Origin juejin.im/post/7085289419850121252
Recomendado
Clasificación