作用域函数存在于Standard.kt中。
主要作用是在一个对象上执行代码块,并提供lambda表达式,从而生成一个临时作用域,而在这个作用域中,我们可以直接访问该对象。

standard文件不大,方法也不算太多,我们都具体的看下:

todo()

@kotlin.internal.InlineOnly
public inline fun TODO(): Nothing = throw NotImplementedError()@kotlin.internal.InlineOnly
public inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason")

在standard.kt中定义了两个todo函数,也就是我们之前在java中使用的注解todo,当我们使用todo函数时,总是会抛出NotImplementedError,从而提示我们当前方法未实现。

run()

run方法有两个,我们先看第一个:

@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return block()
}

老规矩先看源码,
首先standard中的方法都是inline修饰的,也就是内联函数。
接着run方法 传入了参数为R的block函数。
接着我们看下callsInPlace方法。

 @ContractsDsl public fun <R> callsInPlace(lambda: Function<R>, kind: InvocationKind = InvocationKind.UNKNOWN): CallsInPlace

该方法定义传入lambda,并执行,第二个默认参数为InvocationKind.UNKNOWN,代表的lambda执行次数。

InvocationKind是个枚举类,其中有四个值。

public enum class InvocationKind {//至多调用一次@ContractsDsl AT_MOST_ONCE,//至少调用一次@ContractsDsl AT_LEAST_ONCE,//调用一次@ContractsDsl EXACTLY_ONCE,//不知道调用几次@ContractsDsl UNKNOWN
}

run方法最后返回bolock的返回值。

最后我们来看下怎么用:

fun main() {print(stringBuilder())
}
fun stringBuilder(): String {val stringBuilder = StringBuilder()stringBuilder.append("1")stringBuilder.append("2")stringBuilder.append("3")return stringBuilder.toString()
}

上面我们定义了一个方法,返回String。
我们知道run可以传入对象,并且可以直接调用它。那么其实就是省略了
stringBuilder.append,从而直接使用append。

接着我们看run方法的第二个方法:

@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return block()
}

同第一个run的区别就是传入了T扩展函数,也就是当前上下文。

 val s = StringBuilder().run {append("1")append("2")append("3")toString()}print(s)

with

@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return receiver.block()
}

with有两个参数,receiver对象,以及block函数并返回block执行结果。
同样的上面stringbuilder的代码可以改为::

    val sss = with(StringBuilder()) {append("1")append("2")append("3")toString()}println(sss)

apply

@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}block()return this
}

apply与run和with的区别就是以this为传入值,并且返回的是this,而不再是this的扩展函数block的执行结果,

also

@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
}

alse函数则跟apply相似,都是指定传入this,调用block,最后在返回this
,区别就是block不再是this的函数,而是一个普通的函数,只是用对象this来作为参数。

 val n = StringBuilder().also {//这里就不能直接使用append了。it.append("1")it.append("2")it.append("3")}

let

public inline fun <T, R> T.let(block: (T) -> R): R {contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE)}return block(this)
}

整体来看let与also类似,区别就是let返回值是block执行结果,而also则是返回this。

  val a = StringBuilder().let {it.append("1")it.append("2")it.append("3")}

在看另一种情况:

    val sb: StringBuilder? = nullsb?.let {it.append("xxx")}println(sb)


这时候上面的代码就类似与判空操作,与下面的代码相同:

 sb?.append("xxx")

总结:

根据返回值来说:
1:run,with,let返回对象的lambda表达式执行结果
2:also,apply返回上下文对象

另外standard中除了上述五个作用域函数外,还有几个其它的方法,
我们再看下:

@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
}@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {contract {callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)}return if (!predicate(this)) this else null
}

可以看到takeIf和takeUnless其实差不多,区别就是predicate(this)的值是否为true。

  val num = Random.nextInt(100)val takeIf = num.takeIf { it % 2 == 0 }val takeUnless = num.takeUnless { it % 2 == 0 }println("$num ----- $takeIf ---$takeUnless")

如上面所示,我们随机100以内的int值,打印结果如下:

另一点就是,由于takeIf和takeUnless放回值可为空,所以我们如果链式调用其方法时,需要判空。

repeat函数是Standard.kt中的最后一个函数了,

@kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) -> Unit) {contract { callsInPlace(action) }for (index in 0 until times) {action(index)}
}

repeat函数两个参数,一个Int类型的times,另一个action。
另外代码中for循环很简单,根据times的值从0循环执行action。
使用起来很简单,:

   repeat(100) {println("这是repeat的$it")}

如上,我们传入循环次数100,打印结果从0-99.

Kotlin基础篇(二)-作用域函数相关推荐

  1. 用Kotlin撸一个图片压缩插件-插件基础篇(二)

    简述: 前两天写了篇用Kotlin撸一个图片压缩插件-导学篇,现在迎来了插件基础篇,没错这篇文章就是教你如何一步一步从零开始写一个插件,包括插件项目构建,运行,调试到最后的上线发布整个流程.如果你是插 ...

  2. Kotlin教程(二)函数

    写在开头:本人打算开始写一个Kotlin系列的教程,一是使自己记忆和理解的更加深刻,二是可以分享给同样想学习Kotlin的同学.系列文章的知识点会以<Kotlin实战>这本书中顺序编写,在 ...

  3. Kotlin基础 (二)

    Kotlin基础 (二) 11_kotlin命令行交互式终端 12_kotlin函数加强 函数的本质 kotlin函数编写规则 实战编写一个计算器: 作业练习 14_kotlin字符串模版 15_ko ...

  4. mysql 基础篇(二) 账号、权限管理

    mysql 基础篇(二) 账号.权限管理.备份与还原 建立账号密码: Grant all on test.* to "cj"@"localhost" ident ...

  5. VBS基础篇 - 内置函数

    VBS基础篇 - 内置函数 Date/Time 函数 函数 描述 CDate 把有效的日期和时间表达式转换为日期(Date)类型. Date 返回当前的系统日期. DateAdd 返回已添加指定时间间 ...

  6. vue实战入门基础篇二:从零开始仿门户网站实例-开发框架搭建

    上一篇:vue实战入门基础篇一:从零开始仿门户网站实例-前期准备工作 vue实战入门基础篇二:从零开始仿门户网-2022-2-23 21:00:27 一.目录 第一篇:前期准备工作 第二篇:开发框架搭 ...

  7. Python机器学习基础篇二《监督学习》

    前言 前期回顾: Python机器学习基础篇一<为什么用Python进行机器学习> 前面说过,监督学习是最常用也是最成功的机器学习类型之一.本章将会详细介绍监督学 习,并解释几种常用的监督 ...

  8. WF4.0 基础篇 (二) Activity介绍及WriteLine Activity的使用

    从本篇开始,将正式讲解WF4.0,本文主要涉及如下内容:Activity介绍, WF4.0 中工作流的结构,通过WriteLine演示InArgument<T>参数的使用 目录 1     ...

  9. 字符变量赋值规则_Java的常量、变量、数据类型(基础篇二)

    标识符 标识符:是指在程序中自己定义的内容,如类名.方法名.变量名等等. 命名规则:是有硬性要求的 关键字:是指Java已经定义好的单词,具有特殊含义,比如public.static.class.vo ...

  10. 02 MSC类设备-基础篇(二)

    上一篇: https://blog.csdn.net/qq_40088639/article/details/110489923 四.Bulk-Only Transport协议传输模型 分析BusHo ...

最新文章

  1. 计算机在档案管理中的应用,浅谈计算机在档案管理中的应用
  2. 【Jekyll搭建GITHUB个人博客】安装Ruby 环境、包管理器 RubyGems、Jekyll与错误解决...
  3. UVA11991第k次出现的v的下标
  4. c0000005错误怎么解决_iTunes提示3194未知错误怎么办【解决方法】
  5. 新一代神器STM32CubeMonitor介绍、下载、安装和使用教程
  6. 契税申报期限_税局正式公告!财产和行为税合并纳税申报!附税种申报要点
  7. mysql 数据迁移_【AWS 功能】Mysql 数据库迁移至Amazon RDS方案
  8. mysql索引类型和区别是什么意思_mysql主键索引和普通索引之间的区别是什么
  9. 面向兑现编程(四):多态
  10. 面向对象学习(1):认识软件系统的复杂性
  11. vscode markdown preview enhanced css font
  12. 2010-01-22 | 占豪收评:牛市继续还是进入熊市?
  13. NDS CA system和爱迪德CA系统
  14. JAVA面向对象的思维导图
  15. 4位数码管显示模块TM1637芯片C语言驱动程序
  16. BM开发出量子计算机,迄今错误率最低量子比特面世,有望推进量子计算机研发工作...
  17. electron打包后在win7上打开异常KERNEL32.dll
  18. 软件著作权和专利的区别
  19. ESP32 学习日志(4)——OTA升级(1)-示例解析
  20. 全志A10芯片手册资料分享

热门文章

  1. comboxedit不可输入_javafx combobox在edit状态下无法选择
  2. 化工行业ERP管理系统丨外贸软件
  3. Linux知识点总结(思维导图,建议收藏)
  4. redis命令之哈希表类型lpush命令用法详情
  5. No ip domain-lookup和Logging synchronous和Exec-timeout 0 0
  6. ubuntu使用命令设置静态IP地址
  7. 体检信息管理系统功能表
  8. highchart drilldown钻取
  9. [tensorflow] 多维矩阵的乘法
  10. 【Unity 资源分享】☀️ | Unity 华丽炫酷特效资源分享!万年魂环拿到手软,让你直达封号斗罗~