将 if...else null 编写为 ?./?: 链的一部分的惯用 Kotlin 方式是什么?
What's the idiomatic Kotlin way to write `if...else null` as part of ?./?: chains?
(为清晰起见进行了编辑)
我一直发现自己在写 (if (x) f() else null) ?: (if (y) g() else null) ?: (if (z) h() else null)
和类似的东西,我确定我不是唯一一个人
我一直在寻找像下面定义的 valueIf
这样的函数(takeIf
,参数的顺序颠倒了,所以值是惰性的),这样我就可以编写像 getViewEventType2()
而不是像 getViewEventType1()
这样的代码(都在下面详细说明)。
有没有我遗漏的成语?
(此外,编译器对这样的函数是否聪明,或者我是否应该担心创建太多临时闭包?)
private fun getViewEventType1(): String? {
return if (intent.action == "android.intent.action.VIEW") {
intent.data?.pathSegments?.let {
if (it.size == 3 && it[0] == "app" && it[1] == "event") it[2]
else null
}
} else null
}
private fun getViewEventType2(): String? {
return valueIf(intent.action == "android.intent.action.VIEW") {
intent.data?.pathSegments?.let {
valueIf(it.size == 3 && it[0] == "app" && it[1] == "event") { it[2] }
}
}
}
inline fun <T> valueIf(condition: Boolean, func: () -> T?) =
if (condition) func() else null
您仍然可以使用 takeIf()
来实现您想要的,如 Intent
上的扩展函数所示:
fun Intent.getViewEventType(): String? {
return takeIf { it.action == "android.intent.action.VIEW" }
?.`data`
?.pathSegments
?.takeIf { it.size == 3 && it[0] == "app" && it[1] == "event" }
?.get(2)
}
OP 编辑:这是我使用的最终代码:
fun getViewEventType(): String? {
return intent.takeIf { it.action == "android.intent.action.VIEW" }
?.`data`
?.pathSegments
?.takeIf { it.size == 3 && it[0] == "app" && it[1] == "event" }
?.get(2)
}
如 : takeIf
所示,是构建此类结构的方法。
我会把剩下的留在这里给任何感兴趣的人(因为我的评论已经应用):你可能想省略 let
以支持 safe operator ?.
. Additionally you may also be interested in destructing declarations,这使它成为在我看来更具可读性:
fun Intent.getViewEventType() : String? = takeIf { it.action == "android.intent.action.VIEW" }
?.`data`?.pathSegments
?.takeIf { it.size == 3 }
?.takeIf { (source, actionType) -> // destructuring in action... you may want to name the variables appropriately
source == "app" && actionType == "event"
}
?.get(2)
我在这里也使用了single expression function,但我把它留给你了。由于您在此处进行了很多链接,因此您可能至少希望在使用此类构造时指定 return 类型(您也可以省略)。
(为清晰起见进行了编辑)
我一直发现自己在写 (if (x) f() else null) ?: (if (y) g() else null) ?: (if (z) h() else null)
和类似的东西,我确定我不是唯一一个人
我一直在寻找像下面定义的 valueIf
这样的函数(takeIf
,参数的顺序颠倒了,所以值是惰性的),这样我就可以编写像 getViewEventType2()
而不是像 getViewEventType1()
这样的代码(都在下面详细说明)。
有没有我遗漏的成语?
(此外,编译器对这样的函数是否聪明,或者我是否应该担心创建太多临时闭包?)
private fun getViewEventType1(): String? {
return if (intent.action == "android.intent.action.VIEW") {
intent.data?.pathSegments?.let {
if (it.size == 3 && it[0] == "app" && it[1] == "event") it[2]
else null
}
} else null
}
private fun getViewEventType2(): String? {
return valueIf(intent.action == "android.intent.action.VIEW") {
intent.data?.pathSegments?.let {
valueIf(it.size == 3 && it[0] == "app" && it[1] == "event") { it[2] }
}
}
}
inline fun <T> valueIf(condition: Boolean, func: () -> T?) =
if (condition) func() else null
您仍然可以使用 takeIf()
来实现您想要的,如 Intent
上的扩展函数所示:
fun Intent.getViewEventType(): String? {
return takeIf { it.action == "android.intent.action.VIEW" }
?.`data`
?.pathSegments
?.takeIf { it.size == 3 && it[0] == "app" && it[1] == "event" }
?.get(2)
}
OP 编辑:这是我使用的最终代码:
fun getViewEventType(): String? {
return intent.takeIf { it.action == "android.intent.action.VIEW" }
?.`data`
?.pathSegments
?.takeIf { it.size == 3 && it[0] == "app" && it[1] == "event" }
?.get(2)
}
如 takeIf
所示,是构建此类结构的方法。
我会把剩下的留在这里给任何感兴趣的人(因为我的评论已经应用):你可能想省略 let
以支持 safe operator ?.
. Additionally you may also be interested in destructing declarations,这使它成为在我看来更具可读性:
fun Intent.getViewEventType() : String? = takeIf { it.action == "android.intent.action.VIEW" }
?.`data`?.pathSegments
?.takeIf { it.size == 3 }
?.takeIf { (source, actionType) -> // destructuring in action... you may want to name the variables appropriately
source == "app" && actionType == "event"
}
?.get(2)
我在这里也使用了single expression function,但我把它留给你了。由于您在此处进行了很多链接,因此您可能至少希望在使用此类构造时指定 return 类型(您也可以省略)。