Kotlin和惯用的方式来写,'如果不是空的,否则…'基于可变值
假设我们有这样的代码:
class QuickExample { fun function(argument: SomeOtherClass) { if (argument.mutableProperty != null ) { doSomething(argument.mutableProperty) } else { doOtherThing() } } fun doSomething(argument: Object) {} fun doOtherThing() {} } class SomeOtherClass { var mutableProperty: Object? = null }
与Java不同的是,在运行时你可以独自担心空引用问题,但是这并不能正确编译。 当然, mutableProperty
在'if'中可能不再是null。
我的问题是处理这个问题的最好方法是什么?
有几个选项是显而易见的。 在不使用任何新的Kotlin语言功能的情况下,最简单的方法显然是将该值复制到一个方法范围的值,而后者不会随之改变。
有这个:
fun function(argument: SomeOtherClass) { argument.mutableProperty?.let { doSomething(it) return } doOtherThing() }
这有一个明显的缺点,就是你需要尽早返回或者避免执行后面的代码 – 在某些小的上下文中可以,但是却有一定的异味。
那么有这种可能性:
fun function(argument: SomeOtherClass) { argument.mutableProperty.let { when { it != null -> { doSomething(it) } else -> { doOtherThing() } } } }
但是它的目的明确性更高,可以说它比Java处理这种方式更加笨拙和冗长。
我错过了什么,是否有一个成功的成语呢?
我不相信有一个真正的“短”的方式来实现它,但是你可以简单地使用一个条件在或let
:
with(mutableVar) { if (this != null) doSomething(this) else doOtherThing() } mutableVar.let { if (it != null) doSomething(it) else doOtherThing() }
这相当于你的声明。
总是有你描述的选项,把它分配给一个变量:
val immutable = mutableVar if (immutable != null) { doSomething(immutable) } else { doOtherThing() }
在情况变得太冗长的情况下,这总是一个很好的回退。
有可能没有一个非常好的方法来实现这一点,因为只有最后一个 lambda参数被允许放在()
之外,所以指定两个不会真的适合所有其他标准函数的语法。
你可以写一个,如果你不介意的话(或者你会传递方法引用):
inline fun <T : Any, R> T?.ifNotNullOrElse(ifNotNullPath: (T) -> R, elsePath: () -> R) = let { if(it == null) elsePath() else ifNotNullPath(it) }
我会用与猫王运营商 。
mutableProperty?.let { doSomething(it) } ?: doOtherThing()
从文档:
如果?:左边的表达式不为空,则elvis运算符返回它,否则返回右边的表达式。 请注意,右侧的表达式只有在左侧为空时才被评估。
对于右边表达式之后的一段代码:
mutableProperty?.let { doSomething(it) } ?: run { doOtherThing() doOtherThing() }