Kotlin中有多个变量
有没有办法链接多个让kotlin中的多个可为空的变量?
fun example(first: String?, second: String?) { first?.let { second?.let { // Do something just if both are != null } } }
我的意思是,这样的事情:
fun example(first: String?, second: String?) { first?.let && second?.let { // Do something just if both are != null } }
这里有一些变化,取决于你想要使用什么风格,如果你有一切相同或不同的类型,如果名单未知数量的项目…
混合类型,不能为null来计算新的值
对于混合类型,您可以为每个参数计数建立一系列函数,这些函数可能看起来很愚蠢,但对于混合类型很适用:
fun <T1: Any, T2: Any, R: Any> safeLet(p1: T1?, p2: T2?, block: (T1, T2)->R?): R? { return if (p1 != null && p2 != null) block(p1, p2) else null } fun <T1: Any, T2: Any, T3: Any, R: Any> safeLet(p1: T1?, p2: T2?, p3: T3?, block: (T1, T2, T3)->R?): R? { return if (p1 != null && p2 != null && p3 != null) block(p1, p2, p3) else null } fun <T1: Any, T2: Any, T3: Any, T4: Any, R: Any> safeLet(p1: T1?, p2: T2?, p3: T3?, p4: T4?, block: (T1, T2, T3, T4)->R?): R? { return if (p1 != null && p2 != null && p3 != null && p4 != null) block(p1, p2, p3, p4) else null } fun <T1: Any, T2: Any, T3: Any, T4: Any, T5: Any, R: Any> safeLet(p1: T1?, p2: T2?, p3: T3?, p4: T4?, p5: T5?, block: (T1, T2, T3, T4, T5)->R?): R? { return if (p1 != null && p2 != null && p3 != null && p4 != null && p5 != null) block(p1, p2, p3, p4, p5) else null } // ...keep going up to the parameter count you care about
用法示例:
val risk = safeLet(person.name, person.age) { name, age -> // do something }
当列表中没有空项目时,执行代码块
这里有两种风格,第一种是在列表中包含所有非空项目时执行代码块,第二种在列表中至少有一个非空项目时执行相同操作。 两种情况都将非空项目列表传递给代码块:
功能:
fun <T: Any, R: Any> Collection<T?>.whenAllNotNull(block: (List<T>)->R) { if (this.all { it != null }) { block(this.filterNotNull()) } } fun <T: Any, R: Any> Collection<T?>.whenAnyNotNull(block: (List<T>)->R) { if (this.any { it != null }) { block(this.filterNotNull()) } }
用法示例:
listOf("something", "else", "matters").whenAllNotNull { println(it.joinToString(" ")) } // output "something else matters" listOf("something", null, "matters").whenAllNotNull { println(it.joinToString(" ")) } // no output listOf("something", null, "matters").whenAnyNotNull { println(it.joinToString(" ")) } // output "something matters"
让函数获得项目列表并做相同的操作稍作改动:
fun <T: Any, R: Any> whenAllNotNull(vararg options: T?, block: (List<T>)->R) { if (options.all { it != null }) { block(options.filterNotNull()) } } fun <T: Any, R: Any> whenAnyNotNull(vararg options: T?, block: (List<T>)->R) { if (options.any { it != null }) { block(options.filterNotNull()) } }
用法示例:
whenAllNotNull("something", "else", "matters") { println(it.joinToString(" ")) } // output "something else matters"
这些变化可以被改变成像let()
那样的返回值。
使用第一个非空项目(合并)
与SQL合并函数类似,返回第一个非空项目。 两种风格的功能:
fun <T: Any> coalesce(vararg options: T?): T? = options.firstOrNull { it != null } fun <T: Any> Collection<T?>.coalesce(): T? = this.firstOrNull { it != null }
用法示例:
coalesce(null, "something", null, "matters")?.let { it.length } // result is 9, length of "something" listOf(null, "something", null, "matters").coalesce()?.let { it.length } // result is 9, length of "something"
其他变化
…还有其他的变化,但更多的规格可以缩小。
你可以写下你自己的功能:
fun <T, U, R> Pair<T?, U?>.biLet(body: (T, U) -> R): R? { if (first != null && second != null) { return body(first, second) } return null } (first to second).biLet { first, second -> // body }
根据Kotlin的各种*NotNull
和*OrNull
函数的精神,您可以创建一个arrayOfNotNullOrNull
函数,以允许您在所有变量不为null
从“多个可为空的变量”创建一个数组,否则返回null
:
fun <T : Any> arrayOfNotNullOrNull(vararg elements: T?): Array<T>? { for (element in elements) { if (element == null) { return null } } return elements as Array<T> }
然后,您可以使用let
来获取可变数目的值:
fun example(first: String?, second: String?) { arrayOfNotNullOrNull(first, second)?.let { // Do something just if both are != null // eg val (notNullFirst, notNullSecond) = it ... } }
如果你已经有一个集合的空值,那么你可以创建一个类似于kotlin.collections.requireNoNulls
的noNullsOrNull
扩展函数,但是返回null
而不是引发异常。
其实,你可以简单地做到这一点,你知道吗? ;)
if (first != null && second != null) { // your logic here... }
在Kotlin中使用正常的空检查没有任何问题。
对于那些会查看你的代码的人来说,它更具可读性。
对于只检查两个值的情况,也不需要使用列表:
fun <T1, T2> ifNotNull(value1: T1?, value2: T2?, bothNotNull: (T1, T2) -> (Unit)) { if (value1 != null && value2 != null) { bothNotNull(value1, value2) } }
用法示例:
var firstString: String? var secondString: String? ifNotNull(firstString, secondString) { first, second -> Log.d(TAG, "$first, $second") }
- 如何在Kotlin模式匹配可选项?
- 当从kotlin调用java活动结果时,onActivityResult不会被调用
- com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:预期的BEGIN_ARRAY,但在第1行第2列的路径
- Android Kotlin中的Moshi – 将ENUM作为MutableMap键在非集成化时转换为字符串
- “将java代码(不是文件)转换成kotline”
- 动态dsl使用kotlin with content assist
- 带有Scala接收器的函数类型
- Angular:如何在表单提交中发布文件到服务器
- 如何将Kotlin的默认属性值设置为`this`