IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Kotlin学习笔记(六)作用域函数runwith applyalsolettakeIftakeUnlessrepeat -> 正文阅读

[移动开发]Kotlin学习笔记(六)作用域函数runwith applyalsolettakeIftakeUnlessrepeat

作用域函数,就是些技巧性方法,函数定义全在Standard.kt文件里。本篇,用实例记录一下它们的用法。

1.所谓作用域函数:它们的lamda函数作用域===对象类内部作用域。 就像是对象类的内部方法一样。

这样在lamda函数内,可以直接调用对象的方法,属性,不需要通过对象实例点出方法,属性。

2. let/takeIf/takeLess, 需要it引导

3. with是独立函数,其他函数都可由对象点出来。

  • run,利用操作对象的方法属性,完成一些工作。最后在函数体内返回指定值。
        val list = listOf("apple", "orange", "pear")
        val result = StringBuilder().run {
            append("Start eating fruits.\n")
            for (fruit in list){
                append(fruit).append("\n")
            }

            append("Ate all fruits.")

            toString()
        }

        println(result)

  • apply,用于修改对象自己。修改后,如果函数有接收返回,接收的也是修改后的自己。函数体类不需要返回对象。
fun main() {
    val user = User("alan", 18)
    val applyResult = user.apply {
        //这儿都是user对象的作用域
        age = 20
    }
    println(applyResult) //输出:User(name=Peter, age=20)
    println(user) //输出:User(name=Peter, age=20)
    println(applyResult === user) //输出:true
}

data class User(var name: String, var age: Int)

第二个例子:

        val list = listOf("apple", "orange", "pear")
        val result = StringBuilder().apply{
            append("Start eating fruits.\n")
            for (fruit in list){
                append(fruit).append("\n")
            }

            append("Ate all fruits.")
        }

        println(result.toString())
  • with,作用和run一样。不同的是,run由对象点出,而with是独立的函数,对象是作为with的参数。
        val list = listOf("apple", "orange", "pear")
        val result = with(StringBuilder()) {
            append("Start eating fruits.\n")
            for (fruit in list){
                append(fruit).append("\n")
            }

            append("Ate all fruits.")

            toString()
        }

        println(result)

  • let, 把原始对象作为lamda表达式的参数,传入函数体。通常用来简化判空操作, 而且是线程安全的。
object.let{
   it.todo()//在函数体内使用it替代object对象去访问其公有的属性和方法
   ...
}

//另一种用途 判断object为null的操作
object?.let{//表示object不为null的条件下,才会去执行let函数体
   it.todo()
}

?下面的写法,有点罗嗦,如果使用user的参数方法更多,就要被问号烦死了。

    fun doStudy(user:User?){
        user?.age = 20
        user?.name = "alan"
    }

或者用if判空:

    fun doStudy(user:User?){
        if(user != null){
           user.age = 20
           user.name = "alan"
        }
    }

用let函数简化:

    fun doStudy(user:User?){
        user?.let{
        it.age = 20
        it.name = "alan"
    }

针对if判空那种方式,是有问题的。当User对象是全局对象的时候。就编译错误了。提示有多线程问题。

   var user:User? = null
    fun doStudy() {
        if (user!=null) {
            user.age = 20 //编译错误提醒
            user.name = "alan"//编译错误提醒
        }
    }
  • also, 和let的作用一样。不同点就是,let函数的返回值是最后一行的返回值,而also函数的返回值是返回上下文对象本身。可以理解为"并且为该对象执行以下操作"。

一般可用于多个扩展函数链式调用。

fun main() {
    val user = User("alan", 18)
    val alsoResult = user.also {
        println("user 之前的名字是:${it.name}") //user 之前的名字是:alan
    }.apply {
        name = "lin"
    }
    println(alsoResult) //User(name=lin, age=18)
    println(user) //User(name=lin, age=18)
    println(alsoResult === user) //true
}

data class User(var name: String, var age: Int)
  • takeIf,takeunless,?前面调用了一个函数计算得出了一个结果,现在需要对这个结果做一个分支判断,并且我们只需要用到if的一个分支时,可以用takeIf和takeUnless代替。

takeIf,takeunless,?区别就只有一个是满足代码块里面的条件才返回对象本身,一个是不满足条件才返回。

下面三段代码都是等价的:

用if语句:

    fun testWithoutTakeIf() {
        val name = "alan Gong"
        val hasGong = name.indexOf("Gong")
        Log.i(TAG, "testWithoutTakeIf: hasGong = $hasGong")
        if (hasGong >= 0) {
            Log.i(TAG, "testWithoutTakeIf: has Gong")
        }
        Log.i(TAG, "testWithoutTakeIf: $name")
    }
    
输出:
I: testWithoutTakeIf: hasGong = 0
I: testWithoutTakeIf: has Gong 
I: testWithoutTakeIf: alan Gong

用takeIf:

    fun testTakeIf() {
        val name = "alan Gong"
        name.indexOf("Gong")
            .takeIf {
                Log.i(TAG, "testTakeIf: it = $it")
                it >= 0
            }
            ?.let {
                Log.i(TAG, "testTakeIf: has Gong")
            }
        Log.i(TAG, "testTakeIf: $name")
    }
   
输出:
I: testTakeIf: it = 0
I: testTakeIf: has Gong
I: testTakeIf: alan Gong

用takeLess: 注意函数体的判断和takeIf函数体里相反。

    fun testTakeUnless() {
        val name = "alan Gong"
        name.indexOf("Gong")
            .takeUnless {
                Log.i(TAG, "testTakeUnless: it = $it")
                it < 0
            }
            ?.let {
                Log.i(TAG, "testTakeUnless: has Gong")
            }
        Log.i(TAG, "testTakeUnless: $name")
    }
    
输出:
I: testTakeUnless: it = 0
I: testTakeUnless: has  Gong
I: testTakeUnless: alan Gong

由上面的简单例子也可以看出,这两个通常和其他作用域函数,组成链式调用。

  • repeat, 循环执行n次block中的代码。
repeat(3){
    println("repeat")
}

好了,目前所有的作用域函数都记录清楚了。看起来是挺强大的,但是这种东西多了,可读性就不见得好了。另外还有一张网络上的总结图:

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 10:55:38  更:2022-08-06 10:59:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 4:23:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码