高阶函数(higher-order function)是一种特殊的函数, 它接受函数作为参数, 或者返回一个函数. 这种函数的一个很好的例子就是 lock() 函数, 它的参数是一个锁对象(lock object), 以及另一个函数, 它首先获取锁, 运行对象函数, 然后再释放锁:
|
1
2
3
4
5
6
7
8
|
fun <T> lock(lock: Lock, body: () -> T): T {
lock.lock()
try {
return body()
}finally {
lock.unlock()
}
}
|
上面的代码: body 参数是一个 函数类型: () -> T , 因此它应该是一个函数, 这个函数没有参数, 返回一个 T 类型的值。
|
1
2
3
4
5
6
7
8
|
fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
val result = arrayListOf<R>()
for (item in this)
result.add(transform(item))
return result
}
val doubled = ints.map { it -> it * 2 } // 调用
|
函数类型(Function Type)
对于接受另一个函数作为自己参数的函数, 我们必须针对这个参数指定一个函数类型, 例如前面例子的 map 函数,参数 transform 的类型是 (T) -> R, 意思是它是一个函数,参数 T, 返回 R。
引用以及返回一个函数
高阶函数可以接受函数参数,也可以返回一个函数引用, 函数可以赋值给变量,和 C 语言的函数指针一样。
|
1
2
3
4
5
|
fun bar(): (String) -> String = { str -> str.reversed() }
val reversi = bar()
reversi("hello")
reversi("world")
|
内联函数(Inline Function)
Kotlin 支持内联函数,函数内联也许会导致编译产生的代码尺寸变大, 但如果我们使用合理(不要内联太大的函数), 可以换来性能的提高。
|
1
2
3
|
inline fun foo() {
//
}
|
如果一个内联函数的参数中有多个 Lambda 表达式, 而你只希望内联其中的一部分, 你可以对函数的一部分参数添加 noinline 标记。
|
1
2
3
|
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
// ...
}
|
|
1
|
val sum = { x: Int, y: Int -> x + y }
|
Lambda 表达式包含在大括号之内, 在完整语法形式中, 参数声明在圆括号之内, 参数类型的声明可选, 函数体在 -> 符号之后. 如果 Lambda 表达式自动推断的返回值类型不是 Unit , 那么 Lambda 表达式函数体中, 最后一条(或者就是唯一一条)表达式的值, 会被当作整个 Lambda 表达式的返回值。
很多情况下 Lambda 表达式只有唯一一个参数. 如果 Kotlin 能够自行判断出 Lambda 表达式的参数定义,那么它将允许我们省略唯一一个参数的定义, 并且会为我们隐含地定义这个参数, 使用的参数名为 it :
|
1
|
ints.filter { it > 0 }
|
使用 带标签限定的 return 语法, 我们可以在 Lambda 表达式内明确地返回一个结果值. 否则, 会隐含地返回 Lambda 表达式内最后一条表达式的值。
|
1
2
3
4
|
ints.filter {
val shouldFilter = it > 0
return@filter shouldFilter
}
|
匿名函数(Anonymous Function)
匿名函数看起来与通常的函数声明很类似, 区别在于省略了函数名。
|
1
|
fun(x: Int, y: Int): Int = x + y
|
参数和返回值类型的声明与通常的函数一样, 但如果参数类型可以通过上下文推断得到, 那么类型声明可以省略:
|
1
|
ints.filter(fun(item) = item > 0)
|
闭包
所谓闭包,就是一个代码块可以访问外层作用域的变量和参数,例如上面提到的 Lambda 表达式和匿名函数。
|
1
2
3
4
5
6
|
var containsNegative = false
val ints = listOf(0, 1, 2, 3, 4, 5)
ints.forEach {
if (it < 0)
containsNegative = true
}
|
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
原文链接:http://www.jianshu.com/p/212e513ea713
相关文章
- ASP.NET自助建站系统的域名绑定与解析教程 2025-06-10
- 个人服务器网站搭建:如何选择合适的服务器提供商? 2025-06-10
- ASP.NET自助建站系统中如何实现多语言支持? 2025-06-10
- 64M VPS建站:如何选择最适合的网站建设平台? 2025-06-10
- ASP.NET本地开发时常见的配置错误及解决方法? 2025-06-10
- 2025-07-10 怎样使用阿里云的安全工具进行服务器漏洞扫描和修复?
- 2025-07-10 怎样使用命令行工具优化Linux云服务器的Ping性能?
- 2025-07-10 怎样使用Xshell连接华为云服务器,实现高效远程管理?
- 2025-07-10 怎样利用云服务器D盘搭建稳定、高效的网站托管环境?
- 2025-07-10 怎样使用阿里云的安全组功能来增强服务器防火墙的安全性?
快网idc优惠网
QQ交流群
-
2025-06-04 50
-
2025-05-25 38
-
2025-05-27 45
-
2025-06-04 78
-
2025-06-04 84

