Kotlin语言中文站
以另一个函数作为参数或者返回值的函数叫高阶函数, 这个参数函数我们可以用lambda
或者或者函数的引用来表示。 例如集合的filter
就是一个高阶函数
fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
//todo
}
如上:(T) -> Boolean)
是函数类型,因此filter
是接受一个函数作为它的参数,所以符合高阶函数的要求。
我们自己编写一个高阶函数看看:
/**
* 简单Get请求,callback返回String数据
*/
fun requestGet(url: String, callback: (String) -> Unit) {
//request
/* ... */
//返回数据
callback("返回请求的结果")
}
//调用
fun main(args: Array<String>) {
//Lambda表达式的写法:如果函数作为最后一个参数,Lambda表达式可写到圆括号的外面
requestGet("http://www.hepingdev.com/getConfig") { result ->
println(result) //打印:返回请求的结果
}
}
如上:requestGet
函数有两个形参,一个String
类型, 一个函数类型(String) -> Unit
, 请求的String
结果通过这个函数回调返回。其实就是java
当中的接口回调,写法不同。
如何声明函数类型呢?下面一起看看。
声明函数类型,需要将函数参数类型放在圆括号当中,紧接着是一个箭头和函数的返回类型:
(Int, String) -> Unit
, (Int, String)
是参数类型,Unit
是返回类型,这里代表不返回任何值,类似Java
中的void
。
上一节我们学习过,Unit
类型的返回值可以省略不写,但是声明函数类型是需要显式写明返回类型的,所以Unit
不能省略。
像其他函数一样,函数类型的返回值也可以标记为可空类型:
var returnNullFunc: (Int, Int) -> Int? = {x,y -> null}
也可以定义一个变量类型为函数类型的可空变量:
var paramOrNull: ((Int, Int) -> Int)? = null
上面的代码看着可能有点难以理解,我们把函数类型换成字符串类型:
var paramOrNull: String? = null
如上我们定义了个可空的字符串变量,这样比对下就容易理解了,一个变量类型为函数类型(Int, Int) -> Int
,一个变量类型为字符串类型String
。
如上我们一起学习了如何声明一个接收另外的函数作为参数的高阶函数,那返回其他函数的高阶函数呢?
从函数中返回另外一个函数的场景整体来说用得比较少,举个简答得例子:
/**
* 返回函数的函数
*/
fun returnFunc(): (String) -> Unit {
return { info -> println("print##$info") }
}
//调用
fun main(args: Array<String>) {
val getFunc = returnFunc()
getFunc("传递打印的值") //打印: print##传递打印的值
}
上面的代码主要是学习下写法,实际是没有意义的。 后面想到好的例子再补充。
Lambda
表达式的完整语法如下:
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
Kotlin
的Lambda
表达式始终用花括号包围,注意参数并没有用括号括起来,箭头把参数和Lambda
的函数体隔开。
这里记录学习下lambda
表达式的几种写法。
lambda
表达式如果函数的最后一个参数是函数类型,那么相应函数参数传入的lambda
表达式可以直接放在圆括号之外,这种语法也被称为拖尾lambda
表达式:
/**
* 简单Get请求,callback返回String数据, callback函数是最后一个参数
*/
fun requestGet(url: String, callback: (String) -> Unit) {
//request
/* ... */
//返回数据
callback("返回请求的结果")
}
//调用时lambda表达式可以直接放到圆括号之外
requestGet("http://www.hepingdev.com/getConfig") { result ->
println(result) //打印: 返回请求的结果
}
//当然也可以不使用拖尾写法,使用普通的写法
requestGet("", { result -> println(result) })
如果lambda
表达式不是最后一个参数,那么就不能使用拖尾lambda
表达式的写法了。
如果一个lambda
表达式只有一个参数时,可以不用显示写明唯一的参数以及箭头->
。该参数会隐式声明为it
。我们还是拿上面的例子举例:
/**
* 简单Get请求,callback返回String数据
*/
fun requestGet(url: String, callback: (String) -> Unit) {
//request
/* ... */
//返回数据
callback("返回请求的结果")
}
//调用
requestGet("http://www.hepingdev.com/getConfig") {
println(it) //打印: 返回请求的结果
}
如果lambda
表达式具有一个以上的参数呢? 那不好意思,只能显式声明参数,不能忽略:
requestGet("http://www.hepingdev.com/getConfig") {result, count ->
println("request result: $result, array count:$count")
}
如果不使用lambda
表达式中的参数,可以采用下划线_
代替。
requestGet("http://www.hepingdev.com/getConfig") { _, _ ->
println("不使用回调的参数变量")
}
上一篇:Kotlin学习历程——函数与Lambda表达式(一)