0%

自己编的-特殊函数

run()函数

它的实现如下,其实就是调用传入的block参数(一般是个Lambda代码块)

1
2
3
4
5
6
7
8
9
10
11
public inline fun <R> run(block: () -> R): R { 
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}

//使用
run {
myFun()
}

apply() 函数

实现如下,主要看后面两行,先是调用了block函数(block里面可以直接使用this?),然后再返回当前调用者this。即执行完block后返回当前的调用者:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public inline fun <T> T.apply(block: T.() -> Unit): T { 
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}

//使用方法
val a = ArrayList<String>().apply {
add("A")
add("B")
add("C")
println(this)//打印 [A,B,C]
}

println(a)//同样打印 [A,B,C]

let函数

只需要看源代码最后一行即可:意思是把当前调用对象作为参数传入block代码块(意味着一定要用it访问调用对象,能不能this?),最后,返回block执行结果,即作用域中的最后一个对象::

1
2
3
4
5
6
public inline fun <T, R> T.let(block: (T) -> R): R { 
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}

also() 函数

源码先调用block(this) ,但是最后返回值是this,也就是,将当前调用者传入block,执行完后返回调用者。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public inline fun <T> T.also(block: (T) -> Unit): T { 
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block(this)
return this
}

//使用
val a = "ABC".also{
println(it)//输出 ABC
}

pintln(a);//输出 ABC

with() 函数

源码传入一个接收者对象 reciver,然后使用该对象去调用传入的Lambda代码块: receiver.block()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public inline fun <T, R> with(receiver: T, block: T.() -> R): R { 
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver.block()
}

//使用
whith(ArrayList<String>()) {
add("A")
add("B")
add("C")

println(this)//ABC
}.let {
println(it)//kotlin.Unit
}

run、let 与 also 对比

由下面代码可能更好理解run实现中 return block() 、let实现中的 return block(this) ,以及 also 源码中的 return this :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//run提供了一个单独的作用域,并且会返回在这个作用域当中的最后一个对象
//例如现在有这么一个场景,用户领取app的奖励,如果用户没有登录弹出登录dialog,如果已经登录则弹出领取奖励的dialog。我们可以使用以下代码来处理这个逻辑
run {
if (islogin) loginDialog else getAwardDialog
}.show()


val original = "abc"

original.let {
println("The original String is $it") // "abc"
it.reversed()
}.let {
println("The reverse String is $it") // "cba"
it.length
}.let {
println("The length of the String is $it") // 3
}

original.also {
println("The original String is $it") // "abc"
it.reversed()
}.also {
println("The reverse String is ${it}") // "abc"
it.length
}.also {
println("The length of the String is ${it}") // "abc"
}
  • run是直接提供一个作用域,并返回作用域里面最后一个对象
  • let 将this传入block中,并且返回 block(this),也就是作用域最后一个对象
  • also 将this传入block中,但是返回的是 this,也就是调用者本身
  • with 呢,是以 with(T) 的形式使用(但是它貌似不能判断null?)
  • apply没有传入this,但是直接返回this

最后,按需使用的情景:

场景

有些内容参考 无嘴小呆子

无需写interface,直接写个高阶函数?这个地方是不是高阶函数?

谢谢你的鼓励