Kotlin-13-作用域函数

目录

1、定义

2、作用

3、函数:run

4、函数:let

5、函数:apply

5、函数:also

6、函数:takeIf

7、函数:takeUnless

8、函数:with

9、总结


1、定义

对象的扩展函数。

如下图:1、红色框内的就是pig对象所能调用的扩展函数(这些扩展函数对所有对象都适用)

               2、绿色框内就是run扩展函数的源码,具体讲解这个扩展函数的作用

2、作用

可以在这些扩展函数中,对该对象进行进一步的处理。

3、函数:run

它的作用就是将这个函数所得到的值进行返回。

  • 注意:run函数只能返回它的最后一条语句的所得到的值,如下:result2返回的是第二条语句 this.name + "长胖了" 的值。
  • 解决:如果你想要返回第一条语句的值,可以使用return@run方法进行返回。
fun main() {

    val pig = Pig("花姑娘", 300)

    val result1 = pig.run {
        this.name + "长胖了"
    }


    val result2 = pig.run {
        this.name + "长胖了"
        this.weight + 30
    }

    val result3 = pig.run {
        return@run this.name + "长胖了"
        this.weight + 20
    }

    println("result1=$result1")
    println("result2=$result2")
    println("result3=$result3")
}
//输出结果
result1=花姑娘长胖了
result2=330
result3=花姑娘长胖了

4、函数:let

它的作用和run函数一样都是对函数所得到的值进行返回。

  1. 唯一不同:它需要将调用let函数的对象本身,传入到Lambda闭包函数的参数中。
  2. 当然我们可以对这个参数进行简写(Lambda只有一个参数的话,可以省略),省略之后,如果想要调用自身对象的属性可以使用it

如下:let的闭包函数的参数pig1其实就是pig本身。


  val pig = Pig("花姑娘", 300)
 
  val newName = pig.let { pig1: Pig ->
        pig1.name + "瘦了"
    }

  val newName1 = pig.let {
        it.name + "瘦了"
    }

  println("newName=$newName")
  println("newName1=$newName1")

//输出结果
newName=花姑娘瘦了
newName1=花姑娘瘦了

我们可以简单可一下它的源码。这里的let是一个范型方法,T代表对象本身,R代表Lambda闭包函数。

block:(T)-> R  可以看到在lambda函数中的参数就是对象本身T,

return block(this)  代表返回lambda函数的运行结果,

至于中间的 contract 它其实就是一个契约函数,后面我们进行详细讲述。

/**
 * Calls the specified function [block] with `this` value as its argument and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

5、函数:apply

它的返回对象是对象本身,所以我们可以用它对自身属性进行一些操作,再返回本身。(类似于集合的一些操作符)

 后面我附上了源码,可以看到return this,这个this,就是对象本身。

data class Chicken(var name: String, var weight: Int)

fun main() {

    val chicken = Chicken("小母鸡", 30)

    val chickenNew = chicken.apply {
        println("原来的名字:${this.name}")
        this.name = "小花鸡"
    }

    println("现在的名字:${chickenNew.name}")
}

//输出结果
原来的名字:小母鸡
现在的名字:小花鸡

5、函数:also

源码:
/**
 * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
 */
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

它的作用和apply一样,都是返回自己,我们在这里可以对对象本身进行操作, 然后再返回。

区别:also需要将对象本身作为参数传入到lambda函数的参数中,这个区别和run、let的区别一样。

data class Chicken(var name: String, var weight: Int)

fun main() {

    val chicken = Chicken("小母鸡", 30)

    val chickenAlso = chicken.also { chicken1: Chicken ->
        println("原来的重量:${chicken1.weight}")
        chicken1.weight = 40
    }
    
    println("现在的重量:${chickenAlso.weight}")
}
//输出结果
原来的重量:30
现在的重量:40

源码:
/**
 * Calls the specified function [block] with `this` value as its argument and returns `this` value.
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

6、函数:takeIf

//源码:
/**
 * Returns `this` value if it satisfies the given [predicate] or `null`, if it doesn't.
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (predicate(this)) this else null
}

从源码可以看出,它最后返回的是根据Lambda闭包函数predicate的boolean值来决定的。

如果是true就返回对象本身,

如果是false就返回null。

  • 作用:这个函数的作用的话,我们可以在takeif里边对对象本身的属性进行判断,如果符合条件就输出,否则就返回null。
  • 注意1:在takeif里边最后一条语句必须是判断语句,否则就会报错。
  • 注意2:如果有多条判断语句,我们可以根据return@takeIf  来决定返回那条语句的boolean值。
data class Cat(var name: String, var weight: Int)

fun main() {

    val cat=Cat("小花",10)

    val cat1=cat.takeIf {catP: Cat ->
        catP.weight>10
    }
    val cat2 =cat.takeIf {catP: Cat ->
        catP.weight<=10
    }
    val cat3=cat.takeIf {catP: Cat ->
        return@takeIf catP.weight>10
        catP.weight<10
        //1+1//报错
    }

    println("cat1=$cat1")
    println("cat2=$cat2")
    println("cat3=$cat3")

}
//输出结果
cat1=null
cat2=Cat(name=小花, weight=10)
cat3=null

7、函数:takeUnless

它的作用和takeif一样,不同的是它根据闭包函数predicate的boolean值返回的结果相反。

如果是true返回null,

如果是false返回对象本身。

data class Cat(var name: String, var weight: Int)

fun main() {

    val cat = Cat("小花", 10)

    val cat1 = cat.takeIf { catP: Cat ->
        catP.weight > 10
    }
    val cat12 = cat.takeUnless {
        it.weight > 10
    }

    println("cat1=$cat1")
    println("cat12=$cat12")
}
//输出结果
cat1=null
cat12=Cat(name=小花, weight=10)

8、函数:with

//源码
/**
 * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

从源码我们看到它不需要对象来调用它,它其实是一个顶级函数,也就shi你在哪里都可以调用这个函数。

但是它需要两个参数,一个是一个对象receiver,另一个是闭包函数block

它的返回值就是参数对象receiver对闭包函数block的调用结果

  • 可见它的作用可以有很多,比对一个对象进行属性的修改,或这对一个view进行一系列操作,它看起来可以让代码实现了模块化。
data class Cat(var name: String, var weight: Int)

fun main() {

    val cat = Cat("小花", 10)

    val result=with(cat){
        this.name="小白"
        this.weight=11
        1+1
    }

    println("cat.name=${cat.name}")
    println("cat.weight=${cat.weight}")
    println("result=$result")    
}

//输出结果
cat.name=小白
cat.weight=11
result=2

9、总结

这些作用域函数的作用还是具有很多的开放性,你可以用他们来做很多逻辑赋值操作。这就要看你的发挥了。

data class Cat(var name: String, var weight: Int)

fun main() {

    val cat = Cat("小花", 10)

    val newName = cat.also {
        it.name = it.name + "+1"
    }.takeIf {
        it.weight <= 10
    }?.apply {
        this.name = this.name + "+2"
    }?.run {
        return@run name + "+3"
    }

    println("newName=$newName")

}
//输出结果

newName=小花+1+2+3
发布了82 篇原创文章 · 获赞 16 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/qq_34589749/article/details/103569051