let、with、run、apply、also、takeIf、takeUnless、repeat函数的使用
kotlin Standard.kt文件中,提供了一些内联函数,这些内联函数可以减少代码量,在使代码优美的同时,打打提高开发效率。它们分别为:
run、with、let、also、apply
let
let函数的定义如下:
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
默认当前这个对象作为闭包的it参数,函数接受一个lambda函数块返回值是函数里面最后一行,或者指定return
let函数的一般结构为:
obj.let { it.todo//it指代obj对象实例 ... } //在需要判断obj是否为null时 obj?.let { it.todo//it指代obj对象实例 ... }
使用实例:初始化user
val user = User() val result= user.let { it.account = "12306" it.address = "粤海街道" it.address } println(result) //运行结果 >>粤海街道
适用场景:
with
with函数的定义如下:
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
with函数不是以扩展函数的形式存在,它是将对象作为参数,在函数块内通过this指代该对象。with函数是接收了两个参数,分别为对象receiver和一个lambda函数块,返回值为函数块的最后一行或指定return表达式。
with的一般结构为:
with(obj){ this.todo todo//this可省略 ... }
使用实例:将地址影射到UI上
with(user){ tView.text = address }
适用范围:
适用于调用一个类的多个方法,可以省去对象名直接调用方法(例如将数据影射到ui上时)
run
run函数的定义如下:
public inline fun <T, R> T.run(block: T.() -> R): R = block()
run函数接受一个lambda函数块,以闭包的形式返回函数块的最后一行或指定return表达式。观察函数的定义可以发现,run函数为一个扩展函数,而其接受的参数和with函数第二个参数相同,run函数可以理解为let函数和with函数的结合体。
run函数的一般结构为:
obj.run { this.todo todo//this可省略 ... }
使用实例:将地址影射到UI上
user.run { tView.text = address }
适用范围:
适用于let和run函数的场景,run函数相较于let函数省去了必须适用it指代参数的麻烦,相较于with函数弥补了对象判空的问题
also
also函数的定义如下:
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
also函数的定义和let函数的类似,只是also函数返回的为传入对象的本身。
also函数的一般结构和使用方法和let函数类似:
obj.also { it.todo//it指代obj对象实例 ... } //在需要判断obj是否为null时 obj?.let { it.todo//it指代obj对象实例 ... }
适用范围:
also函数返回值微传入方法的对象本身,所以可用来进行函数的链式调用
apply
apply函数的定义如下:
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
apply函数的定义和run函数的类似,唯一的区别就是apply函数返回的为传入对象的本身。
apply函数一般结构如下:
apply函数一般结构如下: obj.apply { this.todo todo//this可省略 ... }
使用实例:给对象赋值
var user = User().apply { account = "12306" }
适用场景:
apply函数和run函数除了返回值外,整体功能和作用类似,一般用于对象初始化时对属性进行赋值。
总结:
这里我们总结对比一下这五个函数,这五个函数的特性非常简单,区别也无非是接受的参数和返回的类型不同。其中,对于with,run,apply接收者是this(可以省略),而let和also则使用it接受且不可s省略对于;
对于with,run,let返回值是返回值是函数里面最后一行,或者指定return,而apply和also返回值是调用者本身。
函数名 | 接受者 | 返回值 |
---|---|---|
let | it | 最后一行 |
with | this | 最后一行 |
run | this | 最后一行 |
also | it | 调用者本身 |
apply | this | 调用者本身 |
如何选择可以参考下图
takeIf、takeUnless、repeat
takeIf & takeUnless
takeIf函数的定义如下:
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null
可以看出:takeIf函数接受一个入参类型为调用者的类型T,返回值为Boolean类型的lambda函数块。takeIf函数根据lambda函数返回值返回的数据,为true返回调用者本身,否则返回null
takeUnless函数的定义如下:
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? = if (!predicate(this)) this else null
不难看出,takeUnless相对比takeIf只是在返回值调用predicate(this)进行了取反操作,takeUnless的作用效果和takeIf正好相反!
takeIf函数一般结构如下:
obj.takeIf{ ... true/fals }
使用实例:
//根据age为user赋值,若age在1-100之间,为user.age赋值age,否则user.age为null var age ... user.age = age.takeIf { age in 1..99 }.toString() user.age = age.ta { age in 100..0 }.toString()
repeat
repeat函数的定义如下:
public inline fun repeat(times: Int, action: (Int) -> Unit) { for (index in 0 until times) { action(index) } }
函数接受一个int类型数据times,和一个入参为int类型,无返回值的lambda函数action,并通过for循环重复的调用times次action函数
函数的一般结构如下:
repeat(int){ todo }
使用实例:
//快速的为list添加十条数据 var list = ArrayList<User>() repeat(10){ list.add(User()) }
适用场景:该函数可以用来避免写循环语句,可以用来遍历数据。
结语:
Kotlin Standard.kt中的标准库函数已基本讲解完毕,其中涉及到了高阶函数和lambda函数,相关知识可通过官方文档学习,同时建议读者将每个函数都实际敲一遍,并通过查看他们编译后的class文件加深对函数的理解。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对小牛知识库的支持。
本文向大家介绍JavaScript中工厂函数与构造函数示例详解,包括了JavaScript中工厂函数与构造函数示例详解的使用技巧和注意事项,需要的朋友参考一下 前言 当谈到JavaScript语言与其他编程语言相比时,你可能会听到一些令人困惑东西,其中之一是工厂函数和构造函数。 工厂函数 所谓工厂函数,就是指这些内建函数都是类对象,当你调用他们时,实际上是创建了一个类实例”。意思就是当我调用这个函
本文向大家介绍MySQL中sleep函数的特殊现象示例详解,包括了MySQL中sleep函数的特殊现象示例详解的使用技巧和注意事项,需要的朋友参考一下 前言 MySQL中的系统函数sleep,实际应用的场景不多,一般用来做实验测试,昨天在测试的时候,意外发现sleep函数的一个特殊现象。如果在查询语句中使用sleep函数,那么休眠的时间跟返回的记录有关。 如下测试所示: 测试总结: 如果,sele
函数是一个可以重复使用的代码块,CPU 会一条一条地挨着执行其中的代码。CPU 在执行主调函数代码时如果遇到了被调函数,主调函数就会暂停,CPU 转而执行被调函数的代码;被调函数执行完毕后再返回到主调函数,主调函数根据刚才的状态继续往下执行。 一个 C/ C++ 程序的执行过程可以认为是多个函数之间的相互调用过程,它们形成了一个或简单或复杂的调用链条,这个链条的起点是 main(),终点也是 ma
从软件工程角度看,将程序实现为一组函数很有好处,但函数调用却会增加执行时的开销。 C++ 提供了内联函数 (inline function) 可以减少函数调用的开销,特别是对于小函数。函数定义中函数返回类型前面的限定符inline指示编译器将函数代码复制到程序中以避免函数调用。其代价是会产生函数代码的多个副本并分别插入到程序中每一个调用该函数的位置上(从而使程序更大),而不是只有一个函数副本(每次
FAQs in section [9]: [9.1] 内联函数有什么用? [9.2] 有没有个简单的例子说明什么是顺序集成(procedure integration)? [9.3] 内联函数能改善性能么? [9.4] 内联函数如何在安全和速度上取得折衷? [9.5] 为什么我应该用内联函数?而不是原来清晰的 #define 宏? [9.6] 如何告诉编译器使非成员函数成为内联函数? [9.7]
C++ 类 & 对象 C++ 内联函数是通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。 对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数。 如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多