Kotlin:Lambda

Posted wzj_what_why_how

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin:Lambda相关的知识,希望对你有一定的参考价值。

/**
 * 1.6.1 let
 */
//上下文对象用it引用,返回Lambda返回的值。
//let()用在调用链的最后面,能省点事,比如:
fun main() {
    val numbers = mutableListOf<String>("one", "tow", "three", "four")
    val resultList = numbers.map { it.length }.filter { it > 3 }
    println(resultList)
}
//改成let后
fun main1() {
    val numbers = mutableListOf<String>("one", "tow", "three", "four")
    val resultList = numbers.map { it.length }.filter { it > 3 }.let { println(it) }
}

fun main2() {
    //还有一种用法,就是判断对象是否为空,如果不为空,则执行Lambda中的代码,并将其上下文对象自动变成不可为空类型。示例如下:
    val str: String? = "Hello"
    //processNonNullString(str)     //--这样调用有错误,因为函数要求参数不可为空,而str可为空

    //正确做法:
    val length = str?.let {
        print("let()   called on $it")
        processNonNullString(it)  //这样调用OK:“it” 以自动变为不可为空
        it.length
    }
}
fun processNonNullString(str: String) {}
//在let中一般放置相关性比较大的对上下文对象的一堆操作,包括设置属性的值、调用方法并对返回值进行运算等。

/**
 * 1.6.2  run()
 */

//上下文对象用this引用,返回Lambda返回回的值
//run的作用有点像let,把对上下文对象相关性比较大的操作放在一起。run和let可以很自然地相互替换,比如:
class  MultiporService(val url: String, val param: Int){
    var port: Int = 8888
    fun query(str: String){}
    fun prepareRequest(): String {return "abc"}

}

val service =  MultiporService("https://google.com", 80)

val result =  service.run {
    port = 8080
    query( "${prepareRequest()} to port $port")
}

val letResult = service.let {
    it.port = 8080
    it.query("${it.prepareRequest()} to port ${it.port}")
}
//run 可以不在某个对象上调用,此时它的作用是将一堆相关的操作放在一起。当然也可以产生结果并返回给某个变量以保存下来,比如:
val hexNumberRegex = run {
    val digits = "0-9"
    val hexDigits = "A-Fa-f"
    val sign = "+-"
    Regex("s$sign]?[$digits$hexDigits]+")
}
fun testHexNumberRegex(){
    for (match in hexNumberRegex.findAll("+1234 -FFFF not-a-number")){
        println(match.value)
    }
}
//注意,hexNumberRegex是一个常量,保存了runzhong Regex()返回的值。

/**
 * 1.6.3  apply()
 */

//上下文对象用this引用,返回上下文对象。
//在此函数Lambda中,主要对上下文对象的属性进行设置,意图是“将这些参数应用到这个对象”,所以一般用于配置对象时。
//看下面的示例代码:

val adam = KotlinBaseKnowledge.Person("Adam").apply {
    age = 32
    city = "London"
}

/**
 * 1.6.4  also()
 */
//上下文对象用it引用,返回上下文对象。
//此函数一般用于调用那些以上下文对象为参数的方法,比如打印上下文对象的属性值,
// 或者将上下文对象的属性值记入日志中,而且不应该在Lambda中更改上下文对象,比如:
fun main3() {
    val numbers = mutableListOf<String>("one", "tow", "three", "four")
    numbers.also {  println(it) }.add("five")
}
//使用also的特点是,如果从调用链中抽走also调用,不会影响调用逻辑和执行结果。

/**
 * 1.6.5 with()
 */

//上下文对象用this引用,返回Lambda返回的值。
//with的作用可以理解为“用这个对象,做点事”。当前面的函数都不大合适时,就可以考虑它了,比如:
fun main4() {
    val numbers = mutableListOf<String>("one", "tow", "three", "four")
    val firstrAndLast  = with(numbers){
        "The first element is ${this[0]} ; The Last element is ${this[this.lastIndex]}"
    }.let { println(it) }
}


//在lanmbda中引用上下文对象时,有的用this,有的用it。run、with、apply用this,this可以省略!
//在返回值方面,apply和also返回的是上下文对象,let,run, with返回的是Lambda中返回的值。


//1.it
//我们知道,用lambda表达式,我们可以把一些函数的写法简化成“输入参数->(运算)输出”,其中,如果只有一个参数时,写出来的代码就像是
//val dints=ints.map{value->value*2}
//对于这种单个参数的运算式,可以进一步简化,把参数声明和->都简化掉,只保留运算输出,不过这要用it来统一代替参数,代码就变成
//val dints2=ints.map{ it*2}
//这就是it的用法,进一步简化单参数的lambda表达式。
//2.let
//let能把更复杂的对象赋给it,比如
//File("a.text").let{
//    it.absoluteFile  //let把file对象赋给了it
//}
//这个特性可以稍微扩展一下,比如增加?检查
//getVaraiable()?.let{
//    it.length    // when not null
//}
//这样可以先检查返回值是否为空,不为空才继续进行
//3.apply
//apply可以操作一个对象的任意函数,再结合let返回该对象,例如
//ints.apply{//拿到一个arraylist对象
//    add(0,3)  //操作该对象的函数
//}.let{ it.size} // 返回该对象(已被修改),继续处理
//4.run
//apply是操作一个对象,run则是操作一块儿代码
//apply返回操作的对象,run的返回则是最后一行代码的对象
//ints.run(){ //操作一个集合
//add(0,3) //操作该集合
//var a=Activity()
//a //会返回最后一行的对象
//}.let{ it.actionBar}
//5.with
//with有点儿像apply,也是操作一个对象,不过它是用函数方式,把对象作为参数传入with函数,然后在代码块中操作,例如
//with(ints){ //传入一个集合
//    add(0,3) //操作该集合
//    var a=Activity()
//    a //会返回最后一行的对象
//}.let{ it.actionBar}
//但是返回像run,也是最后一行
//6.inline
//inline内联函数,其实相当于对代码块的一个标记,这个代码块将在编译时被放进代码的内部,
// 相当于说,内联函数在编译后就被打散到调用它的函数里的,目的是得到一些性能上的优势。

以上是关于Kotlin:Lambda的主要内容,如果未能解决你的问题,请参考以下文章

Kevin Learn Kotlin:Lambda 表达式

如何从片段 KOTLIN 中调用意图 [重复]

Kotlin 中接口的 Lambda 实现

为啥 Kotlin 不能推断以下 lambda 参数(在 Java -> Kotlin 转换之后)?

如何检查 kotlin 中的 lambda 空性

如何在 Kotlin 片段内的按钮之间切换片段?