Rob*_*ham 26 android idioms 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
}
Run Code Online (Sandbox Code Playgroud)
与Java不同,在运行时可以单独担心空解除引用,这不能编译 - 非常正确.当然,mutableProperty在'if'中可能不再为null.
我的问题是处理这个问题的最佳方法是什么?
有一些选择很明显.在不使用任何新的Kotlin语言功能的情况下,最简单的方法显然是将值复制到随后不会更改的方法范围.
有这个:
fun function(argument: SomeOtherClass) {
argument.mutableProperty?.let {
doSomething(it)
return
}
doOtherThing()
}
Run Code Online (Sandbox Code Playgroud)
这有一个明显的缺点,你需要提前返回或以其他方式避免执行后续代码 - 确定在某些小的情况下,但它有一股气味.
然后有这种可能性:
fun function(argument: SomeOtherClass) {
argument.mutableProperty.let {
when {
it != null -> {
doSomething(it)
}
else -> {
doOtherThing()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
虽然它具有更明确的目的,但可以说它比Java风格的处理方式更加笨拙和冗长.
我错过了什么,是否有一个首选的成语来实现这一目标?
Bob*_*Bob 36
更新:
正如franta在评论中所提到的,如果方法doSomething()返回null,那么将执行elvis运算符的乘坐侧的代码,这对于大多数人来说可能不是所希望的情况.但同时,在这种情况下,该方法很可能doSomething()只会做某事而不返回任何东西.
另一种选择:正如protossor在评论中提到的那样,also可以使用而不是let,因为also返回this对象而不是功能块的结果.
mutableProperty?.also { doSomething(it) } ?: doOtherThing()
Run Code Online (Sandbox Code Playgroud)
原始答案:
我会let和Elvis运营商一起使用.
mutableProperty?.let { doSomething(it) } ?: doOtherThing()
Run Code Online (Sandbox Code Playgroud)
来自doc:
如果?:左边的表达式不为null,则elvis运算符返回它,否则返回右边的表达式.请注意,仅当左侧为空时才评估右侧表达式.
对于右侧表达式后面的代码块:
mutableProperty?.let {
doSomething(it)
} ?: run {
doOtherThing()
doOtherThing()
}
Run Code Online (Sandbox Code Playgroud)
Moi*_*ira 14
我不相信有一种真正的"短"方式来实现它,但是你可以简单地使用条件with或let:
with(mutableVar) { if (this != null) doSomething(this) else doOtherThing() }
mutableVar.let { if (it != null) doSomething(it) else doOtherThing() }
Run Code Online (Sandbox Code Playgroud)
实际上,"捕获"可变值是其中一个主要用例let.
这相当于你的when陈述.
总是有你描述的选项,将它分配给变量:
val immutable = mutableVar
if (immutable != null) {
doSomething(immutable)
} else {
doOtherThing()
}
Run Code Online (Sandbox Code Playgroud)
如果事情变得过于冗长,这总是一个很好的后备.
可能没有一种非常好的方法来实现这一点,因为只允许将最后一个 lambda参数放在其外部(),因此指定两个并不真正适合所有其他标准函数的语法.
如果你不介意的话,你可以写一个(或者如果你要传递方法引用):
inline fun <T : Any, R> T?.ifNotNullOrElse(ifNotNullPath: (T) -> R, elsePath: () -> R)
= let { if(it == null) elsePath() else ifNotNullPath(it) }
...
val a: Int? = null
a.ifNotNullOrElse({ println("not null") }, { println("null") })
Run Code Online (Sandbox Code Playgroud)
关于什么:
argument.mutableProperty
?.let { doSomething(it) }
?: doOtherThing()
Run Code Online (Sandbox Code Playgroud)
我通常只是这样做:
when(val it=argument.mutableProperty) {
null -> doOtherThing()
else -> doSomething(it)
}
Run Code Online (Sandbox Code Playgroud)
小智 6
添加自定义内联函数如下:
inline fun <T> T?.whenNull(block: T?.() -> Unit): T? {
if (this == null) block()
return this@whenNull
}
inline fun <T> T?.whenNonNull(block: T.() -> Unit): T? {
this?.block()
return this@whenNonNull
}
Run Code Online (Sandbox Code Playgroud)
那么你可以编写这样的代码:
var nullableVariable :Any? = null
nullableVariable.whenNonNull {
doSomething(nullableVariable)
}.whenNull {
doOtherThing()
}
Run Code Online (Sandbox Code Playgroud)
感谢@zyc zyc,现在我使用这个代码
inline fun <T> T?.ifNull(block: () -> Unit): T? {
if (this == null) block()
return this@ifNull
}
inline fun <T> T?.ifNonNull(block: (T) -> Unit): T? {
this?.let(block)
return this@ifNonNull
}
Run Code Online (Sandbox Code Playgroud)
// use
xxxx.ifNull {
// todo
}.ifNonNull {
// todo
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11993 次 |
| 最近记录: |