Kotlin高阶函数

Kotlin高阶函数高阶函数:如果一个函数接收另一个函数作为参数,或者返回值的类型是另一个函数,那么这个函数就成为高阶函数。写习惯了Java的人可能就在想,编程语言中的参数有整型、字符串类型,布尔型等字段类型,怎么能接收一个函数作为参数呢?其实Kotlin新增了一个函数类型的概念,基本定义规则如下:(String,Int)->Unit看起来有点抽象,一点点解释的话就是->左边括号里的,就是该函数类型要接收的参数类型,可以定义好多个,以逗号隔开;->右边用于声明该函数的返回值是什么类型,如.

  • 高阶函数:如果一个函数接收另一个函数作为参数,或者返回值的类型是另一个函数,那么这个函数就成为高阶函数。

写习惯了Java的人可能就在想,编程语言中的参数有整型、字符串类型,布尔型等字段类型,
怎么能接收一个函数作为参数呢?其实Kotlin新增了一个函数类型的概念,基本定义规则如下:

(String, Int) -> Unit

看起来有点抽象,一点点解释的话就是 ->左边括号里的,就是该函数类型要接收的参数类型,可以定义好多个,以逗号隔开;->右边用于声明该函数的返回值是什么类型,如果没有返回值就写Unit,它大致相当于Java中的void。那么现在将它当做参数传入函数中:

fun test(function: (String, Int) -> Unit) { 
   
        function("123", 123)
    }

现在因为test函数接收一个函数作为参数,那么我们就说test函数是一个高阶函数,高阶函数有什么作用呢,这么说吧,以前我们定义的函数,是用来解决某一个问题的,那现在有了高阶函数,就可以根据传入的这个函数来解决很多个问题了,我举个例子,我们做一个两数之和的函数,如果按普通方法写的话,就是这样:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201123214726679.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E2NDQzODgyNjI=,size_16,color_FFFF
没毛病老铁,算出两数之和了,但是现在calculate只能做加法,我想做两数之差怎么办呢?那就只能再写个方法去相减了,但是现在有了高阶函数,我们可以这么写:
在这里插入图片描述
我把calculate方法改造成了一个高阶函数,除了接收两个Int型的参数之外,最后一个参数接收一个函数,并且这个函数类型的参数的返回值也是Int,在calculate方法中,我们没有做任何事情,只是把参数传给了函数类型的参数,并返回它的返回值。

由于calculate函数接收一个函数类型的参数,所以我们要先定义好相匹配的参数,也就是接收两个Int型参数并且返回值是Int的函数,于是我定义了一个plus函数和一个minus函数,一个用来相加一个用来相减,你看一眼就明白了。

calculate函数的第三个参数我用了::plus和::minus这样的写法,这是一种函数引用方式的写法,表示将plus()和minus()函数作为参数传递给calculate()函数,而由于calculate()函数中使用了传入的函数类型参数来决定具体的运算逻辑,因此这里实际上就是分别使用了plus()和minus()函数来对两个数字进行运算。

但是这样每次都得事先定义好相匹配的函数有点太难搞了,其实我们还可以用 Lanbda表达式来做:
在这里插入图片描述
可以看到,效果是一毛一样的。

我在之前的博客里写apply函数的时候,这么写过:

val builder = AlertDialog.Builder(this).apply { 
   
    setTitle("我是测试title")
    setMessage("我是测试message")
    setNegativeButton("取消", null)
    setPositiveButton("确定", null)
}
builder.show()

创建一个AlertDialog,现在学了高阶函数之后,我们自己手动实现一个apply标准函数,首先新建一个Kotlin file叫MyAlertDialog:
在这里插入图片描述
这里我给AlertDialog.Builder类定义了一个myApply扩展函数,这个扩展函数,这个扩展函数接收一个函数类型参数,并且返回值类型也是AlertDialog.Builder。

注意,这个函数类型参数的声明方式和刚才看到的有所不同:它在函数类型的前面加上了一个AlertDialog.的语法结构。其实这才是定义高阶函数完整的语法规则,在函数类型的前面加上ClassName.就表示这个函数类型是定义在哪个类当中的。

那在这里将其定义为AlertDialog.Builder类当中有什么好处呢?好处就是当我们调用build函数时将闯入的Lambda表达式将会自动拥有AlertDialog.Builder的上下文,同时这也是apply函数的实现方式,现在我们可以用自己创建的myApply函数来实现这个AlertDialog了:

val builder = AlertDialog.Builder(this).myApply { 
   
    setTitle("我是测试title")
    setMessage("我是测试message")
    setNegativeButton("取消", null)
    setPositiveButton("确定", null)
} 
builder.show()

可以看到,myApply函数和apply函数的用法是一毛一样的,只不过这个myApply函数只能作用在AlertDialog.Builder类上面,如果想完全实现apply的功能,需要用到泛型,那我们就按照完全版的高级函数定义公式,定义出我们自己的完整版的myApply函数:

fun <T> T.myApply(block: T.() -> Unit): T { 
   
    block()
    return this
}

首先我们想将myApply函数扩展到哪个类上面呢?我们不知道,那就用泛型代替,那泛型哪里来的呢,所以这里用的是泛型方法< T >,然后将myApply函数扩展到T类上,就是T.myApply,之后的T.()就是上面说的ClassName.就表示这个函数类型是定义在哪个类当中的。最后我们将T返回,这样的话,我们的myApply函数,就和Kotlin中的apply函数一毛一样了!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/37858.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注