Kotlin 必会高级用法

3,123 阅读2分钟

延迟初始化 lateinit , lazy

lateinit, lazy 是 Kotlin 中两种实现延迟初始化的方式.

  • lateinit 只能用于 var 标示的变量,by lazy 只能用于 val 标示的变量。
  • by lazy 只在第一次调用时进行初始化。
class User {
    private lateinit var name: String
    private val password: String by lazy {
        println("lazy init")
        "admin"
    }

    fun setName(name: String) {
        this.name = name
    }

    fun show() {
        println("name = $name")
        println("--------------------")
        println("第一次访问 password = $password")
        println("第二次访问 password = $password")
    }
}

fun main() {
    val user = User()
    user.setName("tomcat")
    user.show()
}

输出结果:

name = tomcat
--------------------
lazy init
第一次访问 password = admin
第二次访问 password = admin

委托 by

/**
 * 定义 Base 接口
 *
 */
interface Base {
    fun say()
}

/**
 * 定义 Base 接口的实现类,并实现 say() 方法
 */
class BaseImpl : Base {
    override fun say() {
        println("BaseImpl say()")
    }
}

/**
 * 定义 BaseProxy 类,并实现了 Base 接口,
 * 关键字 by 将接口 Base 中所有的方法都委托给 base 对象,这样 BaseProxy 类就不需要去实现接口 Base 中的方法了,
 * 简化了实现接口时要实现其中的方法。
 */
class BaseProxy(base: Base) : Base by base

fun main() {
    val baseImpl = BaseImpl()
    // 调用的是 BaseImpl 中的 say() 方法
    BaseProxy(baseImpl).say()
}

输出结果:

BaseImpl say()

扩展函数

扩展函数可以给类额外添加成员函数,通过 "类名.方法名" 方式实现。

/**
 * 定义扩展函数,给 File 添加 readText() 方法
 */
fun File.readText(charset: Charset): String = readBytes().toString(charset)

// 调用
fun main() {
    val file = File("/Users/xing/Desktop/Android.md")
    print(file.readText(Charset.forName("utf-8")))
}

Lambda 闭包

Lambda 表达式本质是 匿名函数,其底层实现是通过 匿名函数来实现的。

特点:

  • Lambda 表达式总是被大括号括着;

  • 其参数(如果存在) , 则在 -> 之前声明;

  • 函数体(如果存在),则在写在 -> 后面;

  • 如果 Lambda 是函数的最后一个参数,可以将大括号放到函数小括号外面。

  • 如果函数只有一个参数且这个参数是 Lambda,则可以省略小括号。