一、高阶函数
高阶函数定义:函数作为参数或者返回值的函数,被称为高阶函数,如下:
1. 函数作为参数
fun main(block: () -> Unit) {
println(block.invoke())
}
2. 函数作为返回值
fun main(block: () -> Unit): (String) -> Unit {
println(block.invoke())
return {} // 返回一个带 String参数的函数
}
3. 高阶函数的作用
- 避免创建过多的接口
- 使用不当,可能会降低可读性
- 在传入函数参数的时候,实际上是创建了匿名内部类,可使用 inline 进行优化
二、Sealed 类
被 Sealed 修饰的类称为密封类,其好处是在作为枚举的时候,能够在编译期穷举所有的状态,避免出现遗漏。
sealed class Status {
companion object LOADING
class SUCCESS(val content: String) : Status()
class FAIL(val msg: String) : Status()
}
三、扩展函数
扩展函数定义:在不修改原类源码的情况下,给某个类型“增加”函数,示例如下:
fun String.copy(content: String): String {
return this + content
}
扩展函数实际上并没有修改原来的代码,上述代码转成 Java 代码如下:
public final class AKt {
@NotNull
public static final String copy(@NotNull String $this$copy, @NotNull String content) {
Intrinsics.checkNotNullParameter($this$copy, "<this>");
Intrinsics.checkNotNullParameter(content, "content");
return $this$copy + content;
}
}
Kotlin 的扩展函数实际上:
- 基于当前文件名生成:filename+Kt,该类是 final 类型
- 生成的函数类型是 static、final
- 把自身作为第一个参数传入函数
四、inline, noinline, crossinline
1. inline
- 消除 lambda 调用创建匿名类对象
- 降低调用栈过深的性能开销
fun show() {
showFace { }
}
inline fun showFace(block: (String) -> Unit) {
println("show face")
}
上述使用 inline 修饰了 showFace() 方法,实际上,show() 会被编译成如下的代码:
public void show() {
String var1 = "show face";
System.out.println(var1);
}
showFace() 的方法直接被 show() 调用。注意 inline 主要作用于高阶函数的作为参数场景,对普通的函数的性能提升影响较小。
2. noline
同样作用于高阶函数的场景,避免某个高阶函数的 lambda 参数被内联。
fun show() {
showFace {}
}
// 第 9 行会在编译期出现报错,给 block 加上 noline 之后,才会消除报错
inline fun showFace(block: (String) -> Unit) {
object : ItemClickListener{
override fun click() {
block.invoke("") // 报错!!!!!!!
}
}
}
interface ItemClickListener {
fun click()
}
当出现如下场景,lambda 参数需要使用 noline 进行修饰:
- lambda 作为参数需要继续传递到下一个函数
- 在匿名内部类中被调用(如上实例)
3. crossinline
它的作用如下:禁止 lambda 使用 return 跳出调用者示例如下:
fun show() {
foo {
return // ❌ 报错!!!!不允许非局部 return
return@foo // ✅ 正确!!!!允许局部返回
}
}
inline fun foo(crossinline block: () -> Unit) {
Runnable {
block()
}.run()
}
还有几个概念:
- crossinline 和 inline 都是可以内联的
- lambda 需要作为参数传递的话,只能使用 noline 修饰,如果只是在匿名内部类调用,也可以使用 crossinline
- noline 和 crossinline 都可以禁止非局部返回