Kotlin 域函数let,apply,run,also,and with

27 阅读2分钟

let

先记住一个结论吧:let it return last ,主要是便于记忆, let 函数使用it作为参数,返回最后一行或者return语句,下面进行解读。我们来看一个场景,要写一个函数,检查是否为null,并根据这个检查返回的结果进行下一步,来看一下。

//应用场景,当你要进行非空检查,并根据检查结果,进行下一步行动时
fun  sendNotification(recipientAddress:String):String {
 println("Yo $recipientAddress")
 return "Notification sent!"
}
fun getNextAddress():String{
 return "getNextAddress@163.com ."
}
fun main(){
    val address:String? = getNextAddress()
    //此处编译报错,原因是 address 是可空的,但是 sendNotification 的参数却不是可空的,使用 if else 判空很好解决
    //sendNotification(address)
    //此处用 let 域函数解决,address 如果为null,就返回 null, 如果不为null,就调用let函数
    val confirm = address?.let {
        sendNotification(it)
    }
    println("confirm = $confirm")
    //let 使用it作为默认参数,最后一行作为返回值
}

输出结果:

Yo getNextAddress@163.com .
confirm = Notification sent!

apply

apply 函数使用this 作为参数,可以省略,返回的也是this, 可以记为: apply this return this ,使用的多的也就熟练的,不用记了

//使用apply域函数可以在创建对象的时候,进行初始化,而不是在后续进行。我们看看下面一个例子

class Client(){
    var token:String?=null
    fun connect() = println("connected!")
    fun authenticate() = println("authenticate!")
    fun getData():String = "Mock data"
}
val client = Client()
fun main(){
    client.token = "abcd"
    client.connect()
    client.authenticate()
    client.getData()
}

输出结果:

connected!
authenticate!

从这个例子中看出,Client 类有一个属性token,有三个方法,在初始化token之前,创建了对象。在实际使用中,在创建实例后,可能要过一段时间才能对其进行配置并使用该实例以及其成员函数,如果用apply函数,则可以同时完成初始化和调用,如下:

val client = Client().apply {
    token = "abcd"
    this.connect()
    authenticate()
}
fun main(){
   client.getData()
}

输出结果:

connected!
authenticate!

run

run 函数函数使用this作为参数,可以省略,返回的是最后一行,或者return语句 简记为: run this return last

class Client(){
    var token:String?=null
    fun connect() = println("connected!")
    fun authenticate() = println("authenticate!")
    fun getData():String = "Mock data"
}
val client = Client().apply {
    token = "abcd"
}
fun main(){
    val result:String = client.run {
        connect()
        authenticate()
        getData()
    }
}

运行结果:

connected!
authenticate!

also

also 使用 it ,返回this, 简记为: also use it return this

fun main(){
    val medals:List<String> = listOf("Gold","Silver","Bronze")
    val reversedLongUppercaseMedals:List<String> =
        //map 的作用:将list中的每个元素转换成新元素,添加到一个新的list中,最后将新的list返回
        medals.map {
            it.uppercase()
        }.also {
            println(it)
        }.filter {
            //过滤长度大于4的元素
            it.length >4
        }.also {
            println(it)
        }.reversed()
    println("reversedLongUppercaseMedals = $reversedLongUppercaseMedals")
}

输出结果:

[GOLD, SILVER, BRONZE]
[SILVER, BRONZE]
reversedLongUppercaseMedals = [BRONZE, SILVER]

with

with 不是扩展函数,使用this作为参数,返回最后一行,或者return语句, with this return last

class Canvas {
    fun rect(x: Int, y: Int, w: Int, h: Int): Unit = println("$x, $y, $w, $h")
    fun circ(x: Int, y: Int, rad: Int): Unit = println("$x, $y, $rad")
    fun text(x: Int, y: Int, str: String): Unit = println("$x, $y, $str")
}
fun main(){
    //用一般的方法实现绘制
    val mainMonitorPrimaryBufferBackedCanvas = Canvas()
    mainMonitorPrimaryBufferBackedCanvas.text(10, 10, "Foo")
    mainMonitorPrimaryBufferBackedCanvas.rect(20, 30, 100, 50)
    mainMonitorPrimaryBufferBackedCanvas.circ(40, 60, 25)
    mainMonitorPrimaryBufferBackedCanvas.text(15, 45, "Hello")
    mainMonitorPrimaryBufferBackedCanvas.rect(70, 80, 150, 100)
    mainMonitorPrimaryBufferBackedCanvas.circ(90, 110, 40)
    mainMonitorPrimaryBufferBackedCanvas.text(35, 55, "World")
    mainMonitorPrimaryBufferBackedCanvas.rect(120, 140, 200, 75)
    mainMonitorPrimaryBufferBackedCanvas.circ(160, 180, 55)
    mainMonitorPrimaryBufferBackedCanvas.text(50, 70, "Kotlin")
    //使用 with 实现调用, with this return last
    with(mainMonitorPrimaryBufferBackedCanvas) {
        text(10, 10, "Foo")
        rect(20, 30, 100, 50)
        circ(40, 60, 25)
        text(15, 45, "Hello")
        rect(70, 80, 150, 100)
        circ(90, 110, 40)
        text(35, 55, "World")
        rect(120, 140, 200, 75)
        circ(160, 180, 55)
        text(50, 70, "Kotlin")
    }
}

参考 kotlin 官网:kotlinlang.org/docs/kotlin…