我想为我的变量分配新值,但如果它为空,我想中断流程,打印出一些日志,然后调用返回。
我的变量类型是 Image 并且不能为 null。
下面是我的解决方案。
我开始的基本代码:
val img = reader.acquireLatestImage() ?: return
我最终创建的代码:
val img : Image = (reader.acquireLatestImage() ?: (Log.d(TAG, "Image is null!").also { return })) as Image
- 这是最好的方法吗?
- 是否可以为此创建扩展?
最佳答案
事实证明编译器不够智能,无法处理 also
在这里,但如果您使用 let
它可以在没有 Actor 的情况下工作:
val img : Image = reader.acquireLatestImage() ?: Log.d(TAG, "Image is null!").let { return }
这是因为 Log.d(...)
的类型是 Unit
,所以类型为 Log.d(...).also { ... }
也是Unit
一般。编译器看不到这种特定情况下的非本地返回会阻止整个表达式 Log.d(...).also { ... }
产生一个值(实际上它应该具有类型 Nothing
,但编译器看不到它,仍然给它类型 Unit
)。
let
相反,返回 lambda 表达式的值,在本例中实际上是 Nothing
类型。因此编译器可以正确理解。
另一种选择是反转您的空处理部分:
val img = reader.acquireLatestImage() ?: return Unit.also { Log.d(TAG, "Image is null!!") }
Is it the best way to do it?
在这种形式下,我什至对我自己的版本都不相信,这可能不是最容易维护的方式。我个人更喜欢简单的 if
此处的日志和return
声明。 Kotlin 与流类型的智能转换将允许您使用 img
类型为 Image
的变量检查后,即使它以类型 Image?
开头:
val img = reader.acquireLatestImage() // this is of type "Image?"
if (img == null) {
Log.d(TAG, "Image is null!")
return
}
// now img is smart-cast to the type Image (non-nullable)
Is it possible to create extension for that?
您无法将非本地返回封装在扩展函数中,但您可以为日志记录创建一个扩展函数,然后使用普通的 elvis 运算符:
fun YourReader.acquireLatestImageOrLog(): Image? {
val img = acquireLatestImage()
if (img == null) {
Log.d(TAG, "Image is null")
}
return img
}
val img = reader.acquireLatestImageOrLog() ?: return
你甚至可以更笼统:
fun <T> T?.orLog(message: String): T? {
if (this == null) {
Log.d(TAG, message)
}
return this
}
val img = reader.acquireLatestImage().orLog("Image is null!") ?: return
关于Kotlin - 为变量赋值或中断并返回函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68778753/