新语言还是多练习的好,不然怎么会遇到问题呢。
遇到的问题
今天依然尝试用 kotlin 写写 demo,加载图片的时候写了下面这段代码。
| 1 | fun loadImageLikeJava(imageUrl: String) { | 
相比正常用 Java 写的逻辑,代码并没有少多少,只是类型推断跟 lambda 让代码看起来干净不少。可是如果这么用 kotlin 并没有多少好,“能不能让代码再少点”,想了一会就改成这样:
| 1 | fun loadImage(imageUrl: String) { | 
用上了 let 跟 also 之后,Callback 里就只剩下一句。
Kotlin 标准库里的这几个内置函数特别好用,但跟其他几个函数一起的话经常容易让人搞混,于是在这里一起总结一下以做记录。
关于 let, also, run, with, apply
先看几个函数的签名:
| 1 | public inline fun <T, R> T.let(block: (T) -> R): R = block(this) | 
- T.apply()跟- T.also()是类似的,他们都可以像 Builder 模式一样链式调用。但- T.apply()的参数是- T.() -> Unit, 即要执行的 block 就像是在 T 内部一样,如果需要调用 T 的方法不需要 it 指明,而- T.also()就需要。
- T.let()跟- T.run()也是类似的,执行函数后返回一个值,就像是 L map R 一样,但- T.run()跟- T.apply()类似,block 都像是在 T 内部一样。
- with()跟- run()跟上面四个函数都不大一样,这两个函数不需要在 T 上调用。- run()是 block 返回一个值 R,跟- Callable有点像,但直接- new Callable()没法直接返回一个值,只能是一个- Callable。
-    with()则是这里面唯一一个接受两个参数的(虽然经过 lambda 表达式的简化之后看起来可以像是一个),第一个参数是接受调用的参数,第二个参数是作用在第一个参数上的方法。这跟T.apply()非常像,但T.apply()返回的是自身,with()执行结束后可以返回其他值。
 
- 简单点记的话是不是可以这样:`also let it go, apply run like inside` 
let 一个常见用法
今天在调用一个 nullable 的对象的时候出现了 kotlin 的 smartcast 「失效」 的情况:
| 1 | var loadDrawable: Drawable = null | 
我本以为经过 != null 的判断,loadDrawable 已经不可能会空,但 IDE 是这么提示的:「无法智能地将 BitmapDrawable? 转换为 BitmapDrawable,因为 loadDrawable 是可变属性,在调用的时候有可能被改变」。仔细想想确实也是,虽然我这里没有没有操作,但一旦有多线程操作,loadDrawable 有可能为 null。如果真的确定不会为 null 或者只会在同一个线程内修改,强制用 loadDrawable!! 是可以的,但有没有更优雅点的方式呢?
有的,就是用 let(also 也可以,但这里并不需要返回 this)。
| 1 | fun loadFinish() { | 
这样编译器就不会再提醒 smart cast 失败了。
参考 let vs if not null